Spaces:
Paused
Paused
Update server.js
Browse files
server.js
CHANGED
|
@@ -8,15 +8,32 @@ const PORT = process.env.PORT || 7860;
|
|
| 8 |
app.use(cors());
|
| 9 |
app.use(express.json());
|
| 10 |
|
| 11 |
-
//
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
// ==========================================
|
| 18 |
// ১. হেলথ চেক রাউট (/health এবং /check)
|
| 19 |
-
// এখানে GET, POST, PUT যাই আসুক না কেন, সার্ভার 'ok' রেসপন্স করবে (ক্রোন জবের জন্য)
|
| 20 |
// ==========================================
|
| 21 |
const healthCheckHandler = (req, res) => {
|
| 22 |
res.status(200).send('ok');
|
|
@@ -27,7 +44,6 @@ app.all('/check', healthCheckHandler);
|
|
| 27 |
|
| 28 |
// ==========================================
|
| 29 |
// ২. সিকিউরিটি মিডলওয়্যার (Middleware)
|
| 30 |
-
// /subscribe এবং /unsubscribe-এ POST ছাড়া অন্য কোনো রিকোয়েست আসলে তা ব্লক করে দেবে
|
| 31 |
// ==========================================
|
| 32 |
const enforcePostOnly = (req, res, next) => {
|
| 33 |
if (req.method !== 'POST') {
|
|
@@ -47,13 +63,11 @@ const enforcePostOnly = (req, res, next) => {
|
|
| 47 |
app.post('/subscribe', enforcePostOnly, async (req, res) => {
|
| 48 |
const { fcm_token, selected_category, action } = req.body;
|
| 49 |
|
| 50 |
-
// ভ্যালিডেশন এবং অ্যাকশন চেক (অ্যাকশন 'subscribe' হওয়া বাধ্যতামূলক)
|
| 51 |
if (!fcm_token || !selected_category || action !== 'subscribe') {
|
| 52 |
return res.status(400).json({ success: false, message: "Invalid payload or wrong action for subscription." });
|
| 53 |
}
|
| 54 |
|
| 55 |
try {
|
| 56 |
-
// ফায়ারবেস টপিক এপিআই কল
|
| 57 |
await admin.messaging().subscribeToTopic(fcm_token, selected_category);
|
| 58 |
console.log(`Successfully subscribed token to topic: ${selected_category}`);
|
| 59 |
|
|
@@ -71,13 +85,11 @@ app.post('/subscribe', enforcePostOnly, async (req, res) => {
|
|
| 71 |
app.post('/unsubscribe', enforcePostOnly, async (req, res) => {
|
| 72 |
const { fcm_token, selected_category, action } = req.body;
|
| 73 |
|
| 74 |
-
// ভ্যালিডেশন এবং অ্যাকশন চেক (অ্যাকশন 'unsubscribe' হওয়া বাধ্যতামূলক)
|
| 75 |
if (!fcm_token || !selected_category || action !== 'unsubscribe') {
|
| 76 |
return res.status(400).json({ success: false, message: "Invalid payload or wrong action for unsubscription." });
|
| 77 |
}
|
| 78 |
|
| 79 |
try {
|
| 80 |
-
// ফায়ারবেস টপিক থেকে রিমুভ করার এপিআই কল
|
| 81 |
await admin.messaging().unsubscribeFromTopic(fcm_token, selected_category);
|
| 82 |
console.log(`Successfully unsubscribed token from topic: ${selected_category}`);
|
| 83 |
|
|
@@ -92,7 +104,7 @@ app.post('/unsubscribe', enforcePostOnly, async (req, res) => {
|
|
| 92 |
});
|
| 93 |
|
| 94 |
// ==========================================
|
| 95 |
-
// ৪. গ্লোবাল ক্যাচ-অল রাউট
|
| 96 |
// ==========================================
|
| 97 |
app.use((req, res) => {
|
| 98 |
res.status(404).json({ success: false, message: "Endpoint not found." });
|
|
|
|
| 8 |
app.use(cors());
|
| 9 |
app.use(express.json());
|
| 10 |
|
| 11 |
+
// ==========================================
|
| 12 |
+
// ০. ফায়ারবেস এডমিন এসডিকে (Hugging Face Secrets থেকে)
|
| 13 |
+
// ==========================================
|
| 14 |
+
try {
|
| 15 |
+
// Hugging Face Secrets থেকে স্ট্রিংটি নেওয়া হচ্ছে
|
| 16 |
+
const secretKeyString = process.env.FIREBASE_SERVICE_ACCOUNT;
|
| 17 |
+
|
| 18 |
+
if (!secretKeyString) {
|
| 19 |
+
throw new Error("FIREBASE_SERVICE_ACCOUNT secret is missing in Hugging Face Spaces settings!");
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
// স্ট্রিংটিকে JSON অবজেক্টে রূপান্তর করা
|
| 23 |
+
const serviceAccount = JSON.parse(secretKeyString);
|
| 24 |
+
|
| 25 |
+
admin.initializeApp({
|
| 26 |
+
credential: admin.credential.cert(serviceAccount)
|
| 27 |
+
});
|
| 28 |
+
|
| 29 |
+
console.log("Firebase Admin SDK initialized successfully using Hugging Face Secrets!");
|
| 30 |
+
} catch (error) {
|
| 31 |
+
console.error("Firebase Initialization Failed:", error.message);
|
| 32 |
+
process.exit(1); // সিক্রেট না থাকলে সার্ভার রান করবে না
|
| 33 |
+
}
|
| 34 |
|
| 35 |
// ==========================================
|
| 36 |
// ১. হেলথ চেক রাউট (/health এবং /check)
|
|
|
|
| 37 |
// ==========================================
|
| 38 |
const healthCheckHandler = (req, res) => {
|
| 39 |
res.status(200).send('ok');
|
|
|
|
| 44 |
|
| 45 |
// ==========================================
|
| 46 |
// ২. সিকিউরিটি মিডলওয়্যার (Middleware)
|
|
|
|
| 47 |
// ==========================================
|
| 48 |
const enforcePostOnly = (req, res, next) => {
|
| 49 |
if (req.method !== 'POST') {
|
|
|
|
| 63 |
app.post('/subscribe', enforcePostOnly, async (req, res) => {
|
| 64 |
const { fcm_token, selected_category, action } = req.body;
|
| 65 |
|
|
|
|
| 66 |
if (!fcm_token || !selected_category || action !== 'subscribe') {
|
| 67 |
return res.status(400).json({ success: false, message: "Invalid payload or wrong action for subscription." });
|
| 68 |
}
|
| 69 |
|
| 70 |
try {
|
|
|
|
| 71 |
await admin.messaging().subscribeToTopic(fcm_token, selected_category);
|
| 72 |
console.log(`Successfully subscribed token to topic: ${selected_category}`);
|
| 73 |
|
|
|
|
| 85 |
app.post('/unsubscribe', enforcePostOnly, async (req, res) => {
|
| 86 |
const { fcm_token, selected_category, action } = req.body;
|
| 87 |
|
|
|
|
| 88 |
if (!fcm_token || !selected_category || action !== 'unsubscribe') {
|
| 89 |
return res.status(400).json({ success: false, message: "Invalid payload or wrong action for unsubscription." });
|
| 90 |
}
|
| 91 |
|
| 92 |
try {
|
|
|
|
| 93 |
await admin.messaging().unsubscribeFromTopic(fcm_token, selected_category);
|
| 94 |
console.log(`Successfully unsubscribed token from topic: ${selected_category}`);
|
| 95 |
|
|
|
|
| 104 |
});
|
| 105 |
|
| 106 |
// ==========================================
|
| 107 |
+
// ৪. গ্লোবাল ক্যাচ-অল রাউট
|
| 108 |
// ==========================================
|
| 109 |
app.use((req, res) => {
|
| 110 |
res.status(404).json({ success: false, message: "Endpoint not found." });
|