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}`);
});