Spaces:
Paused
Paused
| const express = require('express'); | |
| const cors = require('cors'); | |
| const admin = require('firebase-admin'); | |
| const app = express(); | |
| const PORT = process.env.PORT || 7860; | |
| app.use(cors()); | |
| app.use(express.json()); | |
| // ========================================== | |
| // ০. ফায়ারবেস এডমিন এসডিকে (Hugging Face Secrets থেকে) | |
| // ========================================== | |
| try { | |
| // Hugging Face Secrets থেকে স্ট্রিংটি নেওয়া হচ্ছে | |
| const secretKeyString = process.env.FIREBASE_SERVICE_ACCOUNT; | |
| if (!secretKeyString) { | |
| throw new Error("FIREBASE_SERVICE_ACCOUNT secret is missing in Hugging Face Spaces settings!"); | |
| } | |
| // স্ট্রিংটিকে JSON অবজেক্টে রূপান্তর করা | |
| const serviceAccount = JSON.parse(secretKeyString); | |
| admin.initializeApp({ | |
| credential: admin.credential.cert(serviceAccount) | |
| }); | |
| console.log("Firebase Admin SDK initialized successfully using Hugging Face Secrets!"); | |
| } catch (error) { | |
| console.error("Firebase Initialization Failed:", error.message); | |
| process.exit(1); // সিক্রেট না থাকলে সার্ভার রান করবে না | |
| } | |
| // ========================================== | |
| // ১. হেলথ চেক রাউট (/health এবং /check) | |
| // ========================================== | |
| const healthCheckHandler = (req, res) => { | |
| res.status(200).send('ok'); | |
| }; | |
| app.all('/health', healthCheckHandler); | |
| app.all('/check', healthCheckHandler); | |
| // ========================================== | |
| // ২. সিকিউরিটি মিডলওয়্যার (Middleware) | |
| // ========================================== | |
| 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 on this endpoint.` | |
| }); | |
| } | |
| next(); | |
| }; | |
| // ========================================== | |
| // ৩. মূল কার্যকারী রাউট (/subscribe এবং /unsubscribe) | |
| // ========================================== | |
| // --- সাবস্ক্রাইব সেকশন --- | |
| 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 for subscription." }); | |
| } | |
| try { | |
| await admin.messaging().subscribeToTopic(fcm_token, selected_category); | |
| console.log(`Successfully subscribed token to topic: ${selected_category}`); | |
| res.status(200).json({ | |
| success: true, | |
| message: `Successfully registered to ${selected_category} category.` | |
| }); | |
| } catch (error) { | |
| console.error("Firebase subscription error:", 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 for unsubscription." }); | |
| } | |
| try { | |
| await admin.messaging().unsubscribeFromTopic(fcm_token, selected_category); | |
| console.log(`Successfully unsubscribed token from topic: ${selected_category}`); | |
| res.status(200).json({ | |
| success: true, | |
| message: `Successfully removed from ${selected_category} category.` | |
| }); | |
| } catch (error) { | |
| console.error("Firebase unsubscription error:", 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 on port ${PORT}`); | |
| }); | |