♨️

Supabase Cron で定期的に LINE にメッセージを送信する

2024/05/10に公開

このドキュメントについて

Supabase Cron の機能を利用して、定期的に LINE に通知を送ることをゴールにします。
メッセージを送信するユーザーは、users テーブルの中に入っているユーザーのみを対象にします。

手順としては、以下の Step に分けています。
Step1. LINE Bot のアカウントを作成
Step2. Supabase Edge Function の設定
Step3. LINE Push API の利用
Step4. Cron の設定をして、定期実行を設定

Supabase の公式情報

pg_cron: Job Scheduling に公式ドキュメントとしてまとまっています。
動画にもまとまっているので、 Scheduling Edge Functions ぜひ参考にしてください

LINE Messaging API

LINE Messaging API には、ユーザーが送ったメッセージを返信する Reply APIPush API の2種類が存在します。 Reply API は無料で提供されているのですが、Push API は、月に200メッセージまで無料で送信が可能です。詳細は、LINE公式アカウント料金プラン にまとめられています。

Step1. LINE Bot のアカウントを作成

LINE公式アカウントの作成 / LINE Botの初め方 のフローに従い LINE Bot を作成します。

Step2. Supabase Edge Function の設定

users table の作成

Supabase の Dashboard から今回のアプリ用に使うプロジェクトを選択します。登録がない方も Github のアカウントから簡単に作成ができます。
左のタブの 「Table Editor」 > 「New Table」をクリックします。
user-create-page

今回は送信対象の users テーブルを作成します。user_id を varchar でに変更します。
画像のような設定になれば、右下の「Save」ボタンを押すとテーブルが作成されます。

create-users-table

LINE の Bot のページに遷移し、「チャンネル基本設定」のタブにある「あなたのユーザーID」をコピーします。
show-user-id

「Table Editor」 > 「Insert」から、コピーしたユーザーIDを user_id に入力し、新しいカラムを追加します。

created-user-table

「SQL Editor」から SQL を実行することで、実際に users に先ほどの値が登録されていることを確認できます。
execute-sql

関数の作成

supabase コマンドがインストールされていると、以下のコマンドで Edge Functions の作成ができます。

 → supabase functions new push-message
Created new Function at supabase/functions/push-message

users の情報を取得する関数の作成

push-message の index.ts の中身を次のように変更します。

supabase/functions/push-message/index.ts
const supabase = () => createClient(
    // Supabase API URL - env var exported by default.
    Deno.env.get('SUPABASE_URL') ?? '',
    // Supabase API ANON KEY - env var exported by default.
    Deno.env.get('SUPABASE_ANON_KEY') ?? '',
)

Deno.serve(async (req) => {
  const { data, error } = await supabase()
    .from('users')
    .select('user_id')

  // === pushMessage を呼び出すコードを追加 ===

  return new Response(
    JSON.stringify(data),
    { headers: { "Content-Type": "application/json" } },
  )
})

コードを変更が完了すると、 deploy します。

 → supabase functions deploy push-message
Bundling push-message
...
Deploying push-message (script size: 31.25kB)
Deployed Function push-message on project rwnwtaqigqyaxavyjwvs
You can inspect your deployment in the Dashboard: https://supabase.com/dashboard/project/rwnwtaqigqyaxavyjwvs/functions/push-message/details

curl で動作確認

  • FUNCTION_URL:「Edge Functions」 > 「push-message」 のカラムの URL
  • ANON_TOKEN:「Project Settings」> 「API」 > 「Project API keys」 > 「anon public」 からコピー

curl を実行すると user_id のリストが返ってきます。

curl -L -X POST 'FUNCTION_URL' \
    -H 'Authorization: Bearer ANON_TOKEN'
# => [{"user_id":"Ub2f2cc7a09d4456bad5a1176ca8a2087"}]

Step3. LINE Push API の利用

チャンネルアクセストークンを設定する

LINE Bot の画面からチャンネルアクセストークンをコピーします。

line-access-token

「Project Settings」 > 「Edge Functions」 > 「Add new secret」 から LINE Bot のチャンネルアクセストークンを登録します。
Secret name: LINE_CHANNEL_ACCESS_TOKEN
Secret value: LINE Bot のチャンネルアクセストークン

supabase-env-setting

LINE へ PUSH メッセージを送信する

Push Message API を利用するための関数を追加します。

supabase/functions/push-message/index.ts
const pushMessage = (toId, messages) => {
  const dataString = JSON.stringify({
      to: toId,
      messages: messages
  })

  // リクエストヘッダー
  const headers = {
      "Content-Type": "application/json",
      "Authorization": "Bearer " + Deno.env.get('LINE_CHANNEL_ACCESS_TOKEN')
  }

  // https://developers.line.biz/ja/docs/messaging-api/nodejs-sample/#send-reply
  fetch('https://api.line.me/v2/bot/message/push',
      {
          method: "POST",
          body: dataString,
          headers: headers,
      }
  ).then(r => {console.log(r)})
  .catch(e => { console.log(e) })
}

Deno の関数に、pushMessage を呼び出す関数を 1 行追加します。

supabase/functions/push-message/index.ts
Deno.serve(async (req) => {
  const { data, error } = await supabase()
    .from('users')
    .select('user_id')

  // === pushMessage を呼び出すコードを追加 ===
  data.map((d) => pushMessage(
    d.user_id,
    [{type: 'text', text: 'Hello from Functions!'}])
  )
  // === pushMessage を呼び出すコードを追加 ===

  return new Response(
    JSON.stringify(data),
    { headers: { "Content-Type": "application/json" } },
  )
})

もう一度デプロイを行います。

 → supabase functions deploy push-message
Bundling push-message
...
Deploying push-message (script size: 31.25kB)
Deployed Function push-message on project rwnwtaqigqyaxavyjwvs
You can inspect your deployment in the Dashboard: https://supabase.com/dashboard/project/rwnwtaqigqyaxavyjwvs/functions/push-message/details

先ほどと同様に curl から実行すると LINE にメッセージが届いていることがわかります。

curl -L -X POST 'FUNCTION_URL' \
    -H 'Authorization: Bearer ANON_TOKEN'
# => [{"user_id":"Ub2f2cc7a09d4456bad5a1176ca8a2087"}]

Step4. Cron の設定をして、定期実行を設定

cron job を登録する方法

「SQL Editor」から cron の設定を追加します。1分ごとに LINE Push API を呼び出しメッセージを送信します。

select
  cron.schedule(
    'line-bot-cron-job',
    '* * * * *', -- every minute
    $$
    select
      net.http_post(
          url:='https://project-id.supabase.co/functions/v1/cron-schedule',
          headers:='{"Content-Type": "application/json", "Authorization": "Bearer ANON_TOKEN"}'::jsonb,
          body:=concat('{"name": "', now(), '"}')::jsonb
      ) as request_id;
    $$
  );

cron job を確認する

追加した cron は、画面からも確認できます。
「Table Editor」 > 「cron」 > 「job」 を選択すると現在登録されている cron を一覧で確認できます。

supabase-job

「job_run_details」 を選択すると今まで実行された cron も一覧で確認できます。

supabase-job-run-details

cron job を解除する方法

cron の設定を停止するには、「SQL Editor」から unschedule のクエリを実行するだけです。お手軽ですね!!

select cron.unschedule('line-bot-cron-job');

まとめ

Supabase Cron を利用することで簡単に、定期処理を実行することができました。
LINE Push API は月200件までの上限がありますが、LINE Notify では上限がなくメッセージを送信することができます。また、別のドキュメントでまとめようと思います。

Discussion