require("dotenv").config(); const express = require("express"); const cors = require("cors"); const admin = require("firebase-admin"); const fs = require("fs"); const app = express(); app.use(cors()); app.use(express.json()); admin.initializeApp({ credential: admin.credential.cert( require("./serviceAccountKey.json") ), }); const API_KEY = process.env.API_KEY; const TOKEN_FILE = "./tokens.json"; function loadTokens() { try { if (!fs.existsSync(TOKEN_FILE)) return []; const data = fs.readFileSync(TOKEN_FILE, "utf8"); return JSON.parse(data || "[]"); } catch (err) { console.error("[ERROR] Failed to load tokens:", err); return []; } } function saveTokens(tokens) { try { fs.writeFileSync(TOKEN_FILE, JSON.stringify(tokens, null, 2)); } catch (err) { console.error("[ERROR] Failed to save tokens:", err); } } let deviceTokens = new Set(loadTokens()); function authMiddleware(req, res, next) { console.log("[INFO] Incoming request to /push"); const authHeader = req.headers.authorization; if (!authHeader) { return res.status(401).json({ error: "Missing Authorization Header", }); } const token = authHeader.replace("Bearer ", ""); if (token !== API_KEY) { return res.status(403).json({ error: "Invalid API Key", }); } next(); } app.post("/register-token", (req, res) => { console.log("[INFO] /register-token called"); const { token, platform } = req.body; if (!token) { return res.status(400).json({ error: "token required", }); } deviceTokens.add(token); saveTokens([...deviceTokens]); console.log("[INFO] Token registered"); console.log("[DEBUG] Token:", token); console.log("[DEBUG] Platform:", platform || "unknown"); console.log("[INFO] Total tokens:", deviceTokens.size); res.json({ success: true, count: deviceTokens.size, }); }); app.post("/push", authMiddleware, async (req, res) => { console.log("[INFO] /push called"); try { const { type = "none", title, message } = req.body; if (!title || !message) { return res.status(400).json({ error: "title and message required", }); } if (deviceTokens.size === 0) { return res.status(400).json({ error: "No registered device tokens", }); } let color = "#9e9e9e"; switch (type) { case "info": color = "#2196f3"; break; case "warning": color = "#ff9800"; break; case "danger": color = "#f44336"; break; } const messages = []; for (const token of deviceTokens) { messages.push({ token, notification: { title, body: message, }, data: { type, color, }, android: { priority: "high", notification: { color }, }, apns: { payload: { aps: { sound: "default" }, }, }, webpush: { notification: { icon: "/icon-192.png", }, }, }); } console.log("[INFO] Sending messages..."); const response = await admin.messaging().sendEach(messages); console.log("[INFO]:", response.successCount); console.log("[ERROR]:", response.failureCount); res.json({ success: true, successCount: response.successCount, failureCount: response.failureCount, }); } catch (err) { console.error("[ERROR] PUSH:", err); res.status(500).json({ error: err.message, }); } }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log("================================="); console.log("Push Server started"); console.log("Port:", PORT); console.log("Tokens:", TOKEN_FILE); console.log("================================="); });