import { initializeApp, cert } from "firebase-admin/app"; import { getMessaging } from "firebase-admin/messaging"; // Inisialisasi Firebase Admin const serviceAccount = require("./key.json"); try { initializeApp({ credential: cert(serviceAccount), }); console.log("Firebase berhasil diinisialisasi"); } catch (error) { console.error("Gagal inisialisasi Firebase:", (error as Error).message); process.exit(1); } // Fungsi untuk menguji koneksi ke FCM server async function testFCMConnection(): Promise { try { const response = await fetch("https://fcm.googleapis.com", { method: "GET" }); console.log("Koneksi ke FCM server:", response.status, response.statusText); return response.ok; } catch (error) { console.error("Gagal menghubungi FCM server:", (error as Error).message); return false; } } // Fungsi untuk mengirim notifikasi ke banyak perangkat dengan retry async function sendFCMEach(maxRetries: number = 5, retryDelay: number = 2000): Promise { try { // Token perangkat const tokens: string[] = [ "c89yuexsS_uc1tOErVPu5a:APA91bEb6tEKXAfReZjFVJ2mMyOzoW_RXryLSnSJTpbIVV3G0L_DCNkLuRvJ02Ip-Erz88QCQBAt-C2SN8eCRxu3-v1sBzXzKPtDv-huXpkjXsyrkifqvUo", "cRz96GHKTRaQaRJ35e8Hxa:APA91bEUSxE0VPbqKSzseQ_zGhbYsDofMexKykRw7o_3z2aPM9YFmZbeA2enrmb3qjdZ2g4-QQtiNHAyaZqAT1ITOrwo9jVJlShTeABmEFYP5GLEUZ3dlLc", ]; // Validasi token sebelum mengirim const validTokens: string[] = []; for (const token of tokens) { try { await getMessaging().send({ token, notification: { title: "Test", body: "Validasi token" }, }); validTokens.push(token); console.log(`Token ${token.slice(-4)} valid`); } catch (error) { console.error(`Token ${token.slice(-4)} tidak valid:`, (error as Error).message); } } if (validTokens.length === 0) { throw new Error("Tidak ada token valid untuk mengirim notifikasi"); } // Buat pesan untuk setiap token const messages = validTokens.map((token) => ({ notification: { title: "Judul Notifikasi", body: `Pesan untuk perangkat ${token.slice(-4)}`, }, token, data: { key1: "value1", key2: "value2", }, android: { priority: "high", notification: { sound: "default", channelId: "default_channel", }, }, apns: { payload: { aps: { sound: "default", }, }, }, })); console.log("Mengirim notifikasi ke token:", validTokens.map((t) => t.slice(-4))); // Cek koneksi ke FCM server const isConnected = await testFCMConnection(); if (!isConnected) { throw new Error("Gagal terhubung ke FCM server. Periksa jaringan atau firewall."); } // Kirim pesan dengan retry logic let lastError: any; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const response = await getMessaging().sendEach(messages as any); console.log("Notifikasi berhasil dikirim:", response.successCount); console.log("Notifikasi gagal:", response.failureCount); response.responses.forEach((resp: any, index: number) => { if (resp.success) { console.log(`Pesan ke ${validTokens[index].slice(-4)} berhasil:`, resp.messageId); } else { console.error( `Pesan ke ${validTokens[index].slice(-4)} gagal:`, resp.error?.code, resp.error?.message ); } }); return response; } catch (error) { lastError = error; console.error(`Percobaan ${attempt} gagal:`, (error as Error).message); if (error instanceof Error && (error as any).code === "app/network-error" && attempt < maxRetries) { console.log(`Menunggu ${retryDelay}ms sebelum mencoba lagi...`); await new Promise((resolve) => setTimeout(resolve, retryDelay)); } else { throw new Error(`Gagal setelah ${maxRetries} percobaan: ${(error as Error).message}`); } } } throw lastError; } catch (error) { console.error("Error mengirim notifikasi:", (error as Error).message, (error as Error).stack); if ((error as any).code === "messaging/registration-token-not-registered") { console.log("Token tidak valid. Hapus token dari database."); } throw error; } } // Jalankan fungsi async function main() { try { await sendFCMEach(); console.log("Proses selesai"); } catch (error) { console.error("Gagal menjalankan sendFCMEach:", (error as Error).message); process.exit(1); } } main();