Spaces:
Paused
Paused
File size: 5,910 Bytes
209bac3 d0e4741 209bac3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | 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}`);
});
|