import { getAccessToken, getServiceAccount } from './fcmAuth.ts' export async function handleFcmPush(req: Request): Promise { const secret = Deno.env.get('SIDECAR_SECRET') if (secret && req.headers.get('x-sidecar-secret') !== secret) { return new Response('Unauthorized', { status: 401 }) } let body: { tokens: string[] title: string body: string data?: Record } try { body = await req.json() } catch { return new Response('Invalid JSON', { status: 400 }) } const { tokens, title, body: messageBody, data } = body if (!tokens?.length) { return new Response('No tokens provided', { status: 400 }) } const { project_id } = getServiceAccount() const accessToken = await getAccessToken() const results = await Promise.allSettled( tokens.map(token => fetch( `https://fcm.googleapis.com/v1/projects/${project_id}/messages:send`, { method: 'POST', headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ message: { token, notification: { title, body: messageBody }, ...(data ? { data } : {}) } }) } ).then(async (r) => { if (!r.ok) { const err = await r.json() throw new Error(err.error?.message ?? r.statusText) } return r.json() }) ) ) let successCount = 0 let failureCount = 0 results.forEach((result, i) => { if (result.status === 'fulfilled') { successCount++ } else { failureCount++ console.error(`FCM failed for token ${tokens[i]}:`, result.reason) } }) console.log(`FCM: ${successCount} sent, ${failureCount} failed`) return Response.json({ successCount, failureCount }) }