TKK_E32232276/supabase/functions/send-absen-fcm/index.ts

123 lines
4.0 KiB
TypeScript

import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.7.1"
import { GoogleAuth } from "https://esm.sh/google-auth-library@8.7.0"
serve(async (req) => {
try {
const payload = await req.json()
console.log("Webhook Payload:", payload)
const record = payload.record
if (!record) throw new Error("No record found in payload")
const supabaseUrl = Deno.env.get("SUPABASE_URL")
const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")
if (!supabaseUrl || !supabaseServiceKey) throw new Error("Supabase credentials not set")
const supabase = createClient(supabaseUrl, supabaseServiceKey)
let muridId = record.id_murid
let namaUser = record.nama_user || "Siswa"
if (!muridId) {
if (record.rfid) {
const { data: muridData } = await supabase.from("murid").select("id_tabel").eq("rfid", record.rfid).single()
if (muridData) muridId = muridData.id_tabel
} else {
const { data: muridData } = await supabase.from("murid").select("id_tabel").eq("nama", namaUser).single()
if (muridData) muridId = muridData.id_tabel
}
}
let targetUserId = muridId;
if (!targetUserId && namaUser && namaUser !== "Siswa") {
const { data: guruData } = await supabase.from("guru").select("id_tabel").eq("name", namaUser).maybeSingle()
if (guruData) targetUserId = guruData.id_tabel
}
if (!targetUserId) {
return new Response(JSON.stringify({ message: "No target user to notify" }), {
headers: { "Content-Type": "application/json" },
status: 200,
})
}
const query = supabase.from("fcm_tokens").select("token").eq("user_id", targetUserId)
const { data: tokensData, error: tokenError } = await query
if (tokenError) throw tokenError
const tokens = tokensData.map(t => t.token)
if (tokens.length === 0) {
return new Response(JSON.stringify({ message: "No devices to notify" }), {
headers: { "Content-Type": "application/json" },
status: 200,
})
}
console.log(`Found ${tokens.length} tokens to notify.`)
const fcmServiceAccountStr = Deno.env.get("FIREBASE_SERVICE_ACCOUNT")
if (!fcmServiceAccountStr) throw new Error("FIREBASE_SERVICE_ACCOUNT secret is missing")
const serviceAccount = JSON.parse(fcmServiceAccountStr)
const auth = new GoogleAuth({
credentials: {
client_email: serviceAccount.client_email,
private_key: serviceAccount.private_key,
},
scopes: ["https://www.googleapis.com/auth/firebase.messaging"],
})
const accessToken = await auth.getAccessToken()
const message = {
message: {
notification: {
title: "Aplikasi Absensi",
body: `${namaUser} telah melakukan absensi.`
},
data: {
id_murid: muridId || "",
nama_user: namaUser,
id_tabel: record.id_tabel || "",
type: "absen"
}
}
}
const projectId = serviceAccount.project_id
const fcmUrl = `https://fcm.googleapis.com/v1/projects/${projectId}/messages:send`
const promises = tokens.map(async (token) => {
const msg = { ...message, message: { ...message.message, token: token } }
const res = await fetch(fcmUrl, {
method: "POST",
headers: {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify(msg),
})
if (!res.ok) {
console.error(`Failed to send to ${token}:`, await res.text())
}
})
await Promise.all(promises)
return new Response(JSON.stringify({ success: true, notified: tokens.length }), {
headers: { "Content-Type": "application/json" },
status: 200,
})
} catch (error) {
console.error("Error:", error)
return new Response(JSON.stringify({ error: error.message }), {
headers: { "Content-Type": "application/json" },
status: 500,
})
}
})