const express = require('express'); const admin = require('firebase-admin'); const app = express(); app.use(express.json()); // ========================================== // ১. ফায়ারবেজ সেটআপ (Environment Variable থেকে) // ========================================== // Hugging Face-এর Secrets এ FIREBASE_ADMIN JSON স্ট্রিং হিসেবে সেভ করা থাকতে হবে // এবং FIREBASE_DB_URL নামে ডাটাবেজ লিংকটি রাখতে হবে। const serviceAccount = JSON.parse(process.env.FIREBASE_ADMIN); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: process.env.FIREBASE_DB_URL // উদাহরণ: "https://your-project.firebaseio.com" }); const db = admin.database(); // ========================================== // ২. হেলথ চেক রাউটস (যেকোনো রিকোয়েস্ট) // ========================================== const healthHandler = (req, res) => { res.send('Ok yes done'); }; app.all('/health', healthHandler); app.all('/check', healthHandler); app.all('/unps', healthHandler); // ========================================== // ৩. মূল কাজের পাথগুলো // ========================================== const pathGroup1 = ['/link-visit']; const pathGroup2 = ['/adsgram-1', '/adsgram-2', '/gigapub-1', '/gigapub-2', '/monetag-1', '/monetag-2', '/add-account']; const allActionPaths = [...pathGroup1, ...pathGroup2]; // শুধুমাত্র POST রিকোয়েস্ট পারমিট করার মিডলওয়্যার app.use(allActionPaths, (req, res, next) => { if (req.method !== 'POST') { return res.status(405).json({ error: 'Method Not Allowed. Only POST is accepted.' }); } next(); }); // ========================================== // ৪. Cloudflare Turnstile ভ্যালিডেশন মিডলওয়্যার // ========================================== const verifyCloudflare = async (req, res, next) => { // ক্লায়েন্ট থেকে আসা টোকেন (ধরে নিচ্ছি বডিতে 'cf_token' নামে আসবে) const token = req.body.cf_token; if (!token) return res.status(403).json({ error: 'Cloudflare token is missing' }); try { const response = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `secret=${process.env.CLOUDFLIRE_CHECK}&response=${token}` }); const data = await response.json(); if (data.success) { next(); // ভ্যালিডেশন সফল, পরের ধাপে যাও } else { return res.status(403).json({ error: 'Cloudflare verification failed' }); } } catch (error) { return res.status(500).json({ error: 'Server error during Cloudflare verification' }); } }; // ========================================== // ৫. ডাটা প্রসেসিং এবং ফায়ারবেজে সেভ করা // ========================================== app.post(allActionPaths, verifyCloudflare, async (req, res) => { const { user_id, action, 'action_type-1': balance, 'action_type-2': stock } = req.body; // ভ্যালিডেশন: ইউজার আইডি এবং অ্যাকশন চেক if (!user_id || !action) { return res.status(400).json({ error: 'Missing user_id or action' }); } // ভ্যালিডেশন: ডাটা ডিলিট করার রিকোয়েস্ট বাতিল if (action.toLowerCase().includes('delete') || action.toLowerCase() !== 'add') { return res.status(400).json({ error: 'Invalid action. Only "add" is allowed.' }); } const currentPath = req.path; // যেমন: '/link-visit' // ভ্যালিডেশন: ফিক্সড ব্যালেন্স এবং স্টক চেক if (pathGroup1.includes(currentPath)) { if (Number(balance) !== 0.05 || stock !== '+1') { return res.status(400).json({ error: 'Invalid balance or stock for this path. Expected 0.05 and +1.' }); } } else if (pathGroup2.includes(currentPath)) { if (Number(balance) !== 0.06 || stock !== '+1') { return res.status(400).json({ error: 'Invalid balance or stock for this path. Expected 0.06 and +1.' }); } } // ফায়ারবেজে ডাটা সেভ করা try { // ফায়ারবেজে রিকোয়েস্টের পাথের নামেই ডাটা সেভ হবে (যেমন: /link-visit/user_id/...) const dbRef = db.ref(currentPath).child(user_id); const newData = { action: action, balance: Number(balance), stock: stock, timestamp: admin.database.ServerValue.TIMESTAMP }; // ইউজারের নোডের আন্ডারে নতুন ডাটা পুশ করা হলো await dbRef.push(newData); res.status(200).json({ message: 'Success! Data saved to Firebase.', path: currentPath }); } catch (error) { console.error('Firebase Error:', error); res.status(500).json({ error: 'Failed to save data to Firebase' }); } }); // সার্ভার স্টার্ট const PORT = process.env.PORT || 7860; // Hugging Face Space ডিফল্টভাবে 7860 পোর্ট ব্যবহার করে app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });