Spaces:
Sleeping
Sleeping
| const express = require('express'); | |
| const cors = require('cors'); | |
| const admin = require('firebase-admin'); | |
| const app = express(); | |
| const PORT = process.env.PORT || 7860; | |
| const allowedOrigins = [ | |
| 'https://raybil.me', | |
| 'https://story.raybil.me' | |
| ]; | |
| const corsOptions = { | |
| origin: function (origin, callback) { | |
| if (!origin) return callback(null, true); | |
| if (allowedOrigins.indexOf(origin) !== -1) { | |
| callback(null, true); | |
| } else { | |
| callback(null, false); | |
| } | |
| }, | |
| methods: ['POST', 'GET', 'OPTIONS'], | |
| credentials: true | |
| }; | |
| app.use(cors(corsOptions)); | |
| app.use(express.json()); | |
| try { | |
| const secretKeyString = process.env.FIREBASE_SERVICE_ACCOUNT; | |
| if (!secretKeyString) { | |
| throw new Error("FIREBASE_SERVICE_ACCOUNT secret is missing!"); | |
| } | |
| const serviceAccount = JSON.parse(secretKeyString); | |
| admin.initializeApp({ | |
| credential: admin.credential.cert(serviceAccount) | |
| }); | |
| console.log("Firebase Admin SDK initialized successfully!"); | |
| } catch (error) { | |
| console.error("Firebase Initialization Failed:", error.message); | |
| process.exit(1); | |
| } | |
| const healthCheckHandler = (req, res) => { | |
| res.status(200).send('ok'); | |
| }; | |
| app.all('/health', healthCheckHandler); | |
| app.all('/check', healthCheckHandler); | |
| const enforcePostOnly = (req, res, next) => { | |
| if (req.method !== 'POST') { | |
| return res.status(405).json({ | |
| success: false, | |
| message: `Method ${req.method} Not Allowed. Only POST requests are accepted.` | |
| }); | |
| } | |
| next(); | |
| }; | |
| function getSafeTopicName(category) { | |
| const mapping = { | |
| "নবীদের কাহিনী": "nobider_kahini", | |
| "সাহাবিদের জীবনী": "sahabider_jiboni", | |
| "আল-কুরআন ও হাদিসের গল্প": "quran_hadis", | |
| "পূর্বসূরি ও বুজুর্গদের কাহিনী": "scholars_stories", | |
| "শিশুদের ইসলামিক গল্প": "kids_stories" | |
| }; | |
| if (mapping[category]) { | |
| return mapping[category]; | |
| } | |
| return "general_stories"; | |
| } | |
| app.post('/subscribe', enforcePostOnly, async (req, res) => { | |
| const { fcm_token, selected_category, action } = req.body; | |
| if (!fcm_token || !selected_category || action !== 'subscribe') { | |
| return res.status(400).json({ success: false, message: "Invalid payload or wrong action." }); | |
| } | |
| try { | |
| const safeTopic = getSafeTopicName(selected_category); | |
| await admin.messaging().subscribeToTopic(fcm_token, safeTopic); | |
| res.status(200).json({ | |
| success: true, | |
| message: `Successfully registered to ${selected_category} category.` | |
| }); | |
| } catch (error) { | |
| res.status(500).json({ success: false, error: error.message }); | |
| } | |
| }); | |
| app.post('/unsubscribe', enforcePostOnly, async (req, res) => { | |
| const { fcm_token, selected_category, action } = req.body; | |
| if (!fcm_token || !selected_category || action !== 'unsubscribe') { | |
| return res.status(400).json({ success: false, message: "Invalid payload or wrong action." }); | |
| } | |
| try { | |
| const safeTopic = getSafeTopicName(selected_category); | |
| await admin.messaging().unsubscribeFromTopic(fcm_token, safeTopic); | |
| res.status(200).json({ | |
| success: true, | |
| message: `Successfully removed from ${selected_category} category.` | |
| }); | |
| } catch (error) { | |
| res.status(500).json({ success: false, error: error.message }); | |
| } | |
| }); | |
| app.use((req, res) => { | |
| res.status(404).json({ success: false, message: "Endpoint not found." }); | |
| }); | |
| app.listen(PORT, '0.0.0.0', () => { | |
| console.log(`Server is running securely on port ${PORT}`); | |
| }); |