Raybilhelp commited on
Commit
c8eaf5a
·
verified ·
1 Parent(s): a192d44

Update app.js

Browse files
Files changed (1) hide show
  1. app.js +211 -246
app.js CHANGED
@@ -1,290 +1,255 @@
1
  const express = require('express');
2
  const admin = require('firebase-admin');
3
- const crypto = require('crypto'); // Telegram Security-এর জন্য ইনবিল্ট মডিউল
4
-
5
- const app = express();
6
- app.use(express.json());
7
-
8
- // ==========================================
9
- // ০. রিকোয়েস্ট এবং রেসপন্স লগার মিডলওয়্যার (Terminal Console Log)
10
- // ==========================================
11
- app.use((req, res, next) => {
12
- const startTime = Date.now();
13
-
14
- // original res.json এবং res.send মেথড ব্যাকআপ রাখা হচ্ছে রেসপন্স বডি ট্র্যাক করার জন্য
15
- const oldJson = res.json;
16
- const oldSend = res.send;
17
- let responseBody;
18
-
19
- res.json = function(data) {
20
- responseBody = data;
21
- return oldJson.apply(res, arguments);
22
- };
23
 
24
- res.send = function(data) {
25
- responseBody = data;
26
- return oldSend.apply(res, arguments);
27
- };
 
28
 
29
- // রিকোয়্ট হলে টার্মিনলে Docker লগ-এ প্রিন্ট
30
- res.on('finish', () => {
31
- const duration = Date.now() - startTime;
32
- console.log(`\n=========================================`);
33
- console.log(`[${new Date().toISOString()}] ${req.method} -> ${req.originalUrl}`);
34
- console.log(`Status: ${res.statusCode} (${res.statusMessage}) | Time: ${duration}ms`);
35
-
36
- // রিকোয়েস্ট বডি বা কুয়েরি ডেটা দেখা
37
- if (Object.keys(req.body).length > 0) {
38
- // সিকিউরিটির জন্য এবং টার্মিনাল ক্লিন রাখতে বড় init_data হাইড করা হয়েছে
39
- const cleanBody = { ...req.body };
40
- if (cleanBody.init_data) cleanBody.init_data = "[TELEGRAM_INIT_DATA_HIDDEN]";
41
- console.log(`Request Body:`, JSON.stringify(cleanBody, null, 2));
42
- } else if (Object.keys(req.query).length > 0) {
43
- console.log(`Request Query:`, JSON.stringify(req.query, null, 2));
 
 
 
 
 
 
44
  }
 
 
 
 
 
 
 
 
 
45
 
46
- // সার্ভার ক্লায়েন্টকে কী রিপ্লাই দিল তা প্রিন্ট করা
47
- if (responseBody) {
48
- console.log(`Server Reply:`, typeof responseBody === 'object' ? JSON.stringify(responseBody, null, 2) : responseBody);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
- console.log(`=========================================`);
51
- });
52
 
53
- next();
54
- });
 
 
 
55
 
56
- // ==========================================
57
- // ১. ফায়ারবেজ মাল্টিপল অ্যাডমিন সেটআপ
58
- // ==========================================
59
- const initFirebase = (envAdmin, envUrl, appName) => {
60
- if (!process.env[envAdmin] || !process.env[envUrl]) {
61
- console.warn(`Warning: ${envAdmin} or ${envUrl} is missing.`);
62
- return null;
63
- }
64
- return admin.initializeApp({
65
- credential: admin.credential.cert(JSON.parse(process.env[envAdmin])),
66
- databaseURL: process.env[envUrl]
67
- }, appName);
68
- };
69
-
70
- const app1 = initFirebase('FIREBASE_ADMIN_1', 'FIREBASE_DB_URL_1', 'Admin1');
71
- const app3 = initFirebase('FIREBASE_ADMIN_3', 'FIREBASE_DB_URL_3', 'Admin3');
72
- const app4 = initFirebase('FIREBASE_ADMIN_4', 'FIREBASE_DB_URL_4', 'Admin4');
73
-
74
- const db1 = app1 ? app1.database() : null;
75
- const db3 = app3 ? app3.database() : null;
76
- const db4 = app4 ? app4.database() : null;
77
-
78
- // ==========================================
79
- // ২. হেলথ চেক রাউটস (যেকোনো রিকোয়েস্ট)
80
- // ==========================================
81
- const healthHandler = (req, res) => {
82
- res.send('Ok, yes, done');
83
- };
84
- app.all('/health', healthHandler);
85
- app.all('/ch', healthHandler);
86
- app.all('/unps', healthHandler);
87
-
88
- // ==========================================
89
- // ৩. মিডলওয়্যার: শুধুমাত্র POST রিকোয়েস্ট পারমিট করা
90
- // ==========================================
91
- const checkPostMethod = (req, res, next) => {
92
- if (req.method !== 'POST') {
93
- return res.status(405).json({ error: 'Method Not Allowed. Only POST is accepted.' });
94
- }
95
- next();
96
- };
97
 
98
- // ==========================================
99
- // ৪. Telegram Security ভ্যালিডেশন মিডলওয়্যার
100
- // ==========================================
101
- const verifyTelegramAuth = (req, res, next) => {
102
- const { init_data, user_id, name } = req.body;
103
 
104
- if (!init_data) return res.status(401).json({ error: 'Unauthorized: init_data is missing' });
 
 
105
 
106
- try {
107
- const botToken = process.env.BOT_TOKEN;
108
- if (!botToken) return res.status(500).json({ error: 'Server configuration error' });
 
109
 
110
- const urlParams = new URLSearchParams(init_data);
111
- const hash = urlParams.get('hash');
112
- urlParams.delete('hash');
113
 
114
- const dataToCheck = [...urlParams.entries()]
115
- .map(([key, value]) => `${key}=${value}`)
116
- .sort()
117
- .join('\n');
118
 
119
- const secretKey = crypto.createHmac('sha256', 'WebAppData').update(botToken).digest();
120
- const calculatedHash = crypto.createHmac('sha256', secretKey).update(dataToCheck).digest('hex');
121
 
122
- if (calculatedHash !== hash) {
123
- return res.status(403).json({ error: 'Forbidden: Invalid Telegram signature' });
124
- }
125
 
126
- const tgUser = JSON.parse(urlParams.get('user'));
 
 
 
127
 
128
- // আইডি এবং নাম হুবহু সেম কি না তা চেক করা
129
- if (String(tgUser.id) !== String(user_id)) {
130
- return res.status(403).json({ error: 'Forbidden: User ID mismatch' });
131
  }
 
132
 
133
- const tgFullName = tgUser.last_name ? `${tgUser.first_name} ${tgUser.last_name}`.trim() : tgUser.first_name;
134
- if (String(tgFullName) !== String(name) && String(tgUser.first_name) !== String(name)) {
135
- return res.status(403).json({ error: 'Forbidden: Name mismatch' });
136
- }
 
137
 
138
- next(); // সব ঠিক থাকলে মূল লজিকে যাবে
139
- } catch (error) {
140
- console.error('Telegram Validation Error:', error);
141
- return res.status(500).json({ error: 'Internal server error during validation' });
142
- }
143
- };
144
 
145
- // ==========================================
146
- // . API: ক্রিয়েট অ্যাকাউন্ট (/creataccoumt)
147
- // ==========================================
148
- app.post('/creataccoumt', checkPostMethod, verifyTelegramAuth, async (req, res) => {
149
- const { user_id, refer_id, name, username, profile_pic_url } = req.body;
150
 
151
- try {
152
- const userRef = db1.ref('user').child(user_id);
153
- const snapshot = await userRef.once('value');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
- if (snapshot.exists()) {
156
- return res.status(200).json({ message: 'Account already exists. No action taken.' });
 
157
  }
 
158
 
159
- const newUserData = {
160
- user_id,
161
- refer_id: refer_id || null,
162
- name: name || null,
163
- username: username || null,
164
- profile_pic_url: profile_pic_url || null,
165
- balance: 0,
166
- total_withdraw: 0,
167
- total_withdraw_amount: 0,
168
- join_date: admin.database.ServerValue.TIMESTAMP,
169
- total_refer: 0
170
- };
171
-
172
- await userRef.set(newUserData);
173
-
174
- if (refer_id) {
175
- const referUserRef = db1.ref('user').child(refer_id);
176
- const referUserSnap = await referUserRef.once('value');
177
-
178
- if (referUserSnap.exists()) {
179
- await referUserRef.child('total_refer').transaction((currentValue) => {
180
- return (currentValue || 0) + 1;
181
- });
182
-
183
- const referListRef = db3.ref('refer').child(refer_id);
184
- await referListRef.push(user_id);
185
- }
186
- }
187
 
188
- res.status(201).json({ message: 'Account created successfully!' });
189
- } catch (error) {
190
- console.error('Account Creation Error:', error);
191
- res.status(500).json({ error: 'Internal Server Error' });
192
- }
193
- });
194
 
195
- // ==========================================
196
- // ৬. API: উইথড্র মেইন ব্যালেন্স (/withdraw-main)
197
- // ==========================================
198
- app.post('/withdraw-main', checkPostMethod, verifyTelegramAuth, async (req, res) => {
199
- const { user_id, method, address, time, amount } = req.body;
200
- const allowedMethods = ['bkash', 'mobile-gp', 'mobile-ar', 'mobile-ro', 'mobile-bl', 'mobile-tk', 'nagad', 'binance', 'usdt', 'ton'];
201
 
202
- if (!method || !address || !amount) return res.status(400).json({ error: 'Missing required fields' });
203
- if (!allowedMethods.includes(method)) return res.status(400).json({ error: 'Invalid withdrawal method' });
204
 
205
- try {
206
- const userRef = db1.ref('user').child(user_id);
207
- const snapshot = await userRef.once('value');
208
 
209
- if (!snapshot.exists()) return res.status(404).json({ error: 'User not found' });
 
 
210
 
211
- const userData = snapshot.val();
212
- const currentBalance = Number(userData.balance || 0);
213
- const requestAmount = Number(amount);
 
 
 
 
 
 
 
214
 
215
- if (currentBalance < requestAmount) {
216
- return res.status(400).json({ error: 'Insufficient balance' });
 
217
  }
 
218
 
219
- await userRef.child('balance').set(currentBalance - requestAmount);
220
-
221
- const pendingRef = db3.ref('withdrow/painding').child(user_id);
222
- await pendingRef.push({
223
- method,
224
- address,
225
- time: time || admin.database.ServerValue.TIMESTAMP,
226
- amount: requestAmount,
227
- status: 'pending'
228
- });
229
-
230
- res.status(200).json({ message: 'Withdrawal request successful' });
231
- } catch (error) {
232
- console.error('Withdraw Main Error:', error);
233
- res.status(500).json({ error: 'Internal Server Error' });
234
- }
235
- });
236
-
237
- // ==========================================
238
- // ৭. API: অ্যাড ব্যালেন্স উইথড্র (Admin 4 -> Admin 1)
239
- // ==========================================
240
- const adWithdrawPaths = [
241
- '/withdraw-link-visit',
242
- '/withdraw-adsgram-1',
243
- '/withdraw-adsgram-2',
244
- '/withdraw-gigapub-1',
245
- '/withdraw-gigapub-2',
246
- '/withdraw-monetag-1',
247
- '/withdraw-monetag-2'
248
- ];
249
-
250
- app.post(adWithdrawPaths, checkPostMethod, async (req, res) => {
251
- const { user_id, amount, method } = req.body;
252
-
253
- if (!user_id || !amount || method !== 'wallet') {
254
- return res.status(400).json({ error: 'Invalid request. Method must be wallet and amount is required.' });
255
- }
256
 
257
- const adNetworkName = req.path.replace('/withdraw-', '');
258
- const requestAmount = Number(amount);
259
 
260
- try {
261
- const adRef = db4.ref(adNetworkName).child(user_id);
262
- const adSnapshot = await adRef.once('value');
263
 
264
- if (!adSnapshot.exists()) return res.status(404).json({ error: 'No ad earnings found for this user' });
265
 
266
- let adCurrentBalance = Number(adSnapshot.val().balance || 0);
267
 
268
- if (adCurrentBalance < requestAmount) {
269
- return res.status(400).json({ error: 'Insufficient ad balance' });
270
- }
271
 
272
- await adRef.child('balance').set(adCurrentBalance - requestAmount);
273
 
274
- const mainUserRef = db1.ref('user').child(user_id);
275
- await mainUserRef.child('balance').transaction((currentMainBalance) => {
276
- return (currentMainBalance || 0) + requestAmount;
277
- });
278
 
279
- res.status(200).json({ message: `Success! ${requestAmount} transferred to main balance from ${adNetworkName}` });
280
- } catch (error) {
281
- console.error('Ad Withdraw Error:', error);
282
- res.status(500).json({ error: 'Internal Server Error' });
283
- }
284
- });
285
 
286
- // সার্ভার স্টার্ট
287
- const PORT = process.env.PORT || 7860;
288
- app.listen(PORT, () => {
289
- console.log(`Server is running on port ${PORT}`);
290
- });
 
1
  const express = require('express');
2
  const admin = require('firebase-admin');
3
+ const crypto = require('crypto');
4
+ const cluster = require('cluster');
5
+ const os = require('os');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ // সার্ভারের মোট সিপিইউ কোর সংখ্যা স্বয়ংক্রিয়ভাবে ডিটেক্ট করা (১২ কোর হলে ১২টি প্রসেস তৈরি হবে)
8
+ const numCPUs = os.cpus().length;
9
+
10
+ if (cluster.isMaster) {
11
+ console.log(`Master Server Process ${process.pid} is running. Detecting ${numCPUs} CPU cores...`);
12
 
13
+ // প্িটি কোর জনয একি করওয়ার্ ভা তৈরি করা চ্ছ
14
+ for (let i = 0; i < numCPUs; i++) {
15
+ cluster.fork();
16
+ }
17
+
18
+ // কোনো ওয়ার্কার কোনো কারণে ক্র্যাশ করলে স্বয়ংক্রিয়ভাবে নতুন ওয়ার্কার চালু হবে
19
+ cluster.on('exit', (worker, code, signal) => {
20
+ cluster.fork();
21
+ });
22
+
23
+ } else {
24
+ // এটি হলো ওয়ার্কার প্রসেস - যা আসল ট্রাফিক হ্যান্ডেল করবে
25
+ const app = express();
26
+ app.use(express.json());
27
+
28
+ // ==========================================
29
+ // ১. ফায়ারবেজ মাল্টিপল অ্যাডমিন সেটআপ
30
+ // ==========================================
31
+ const initFirebase = (envAdmin, envUrl, appName) => {
32
+ if (!process.env[envAdmin] || !process.env[envUrl]) {
33
+ return null;
34
  }
35
+ return admin.initializeApp({
36
+ credential: admin.credential.cert(JSON.parse(process.env[envAdmin])),
37
+ databaseURL: process.env[envUrl]
38
+ }, appName);
39
+ };
40
+
41
+ const app1 = initFirebase('FIREBASE_ADMIN_1', 'FIREBASE_DB_URL_1', 'Admin1');
42
+ const app3 = initFirebase('FIREBASE_ADMIN_3', 'FIREBASE_DB_URL_3', 'Admin3');
43
+ const app4 = initFirebase('FIREBASE_ADMIN_4', 'FIREBASE_DB_URL_4', 'Admin4');
44
 
45
+ const db1 = app1 ? app1.database() : null;
46
+ const db3 = app3 ? app3.database() : null;
47
+ const db4 = app4 ? app4.database() : null;
48
+
49
+ // ==========================================
50
+ // ২. হেলথ চেক রাউটস (যেকোনো রিকোয়েস্ট)
51
+ // ==========================================
52
+ const healthHandler = (req, res) => {
53
+ res.send('Ok, yes, done');
54
+ };
55
+ app.all('/health', healthHandler);
56
+ app.all('/ch', healthHandler);
57
+ app.all('/unps', healthHandler);
58
+
59
+ // ==========================================
60
+ // ৩. মিডলওয়্যার: শুধুমাত্র POST রিকোয়েস্ট পারমিট করা
61
+ // ==========================================
62
+ const checkPostMethod = (req, res, next) => {
63
+ if (req.method !== 'POST') {
64
+ return res.status(405).json({ error: 'Method Not Allowed. Only POST is accepted.' });
65
  }
66
+ next();
67
+ };
68
 
69
+ // ==========================================
70
+ // ৪. Telegram Security ভ্যালিডেশন মিডলওয়্যার
71
+ // ==========================================
72
+ const verifyTelegramAuth = (req, res, next) => {
73
+ const { init_data, user_id, name } = req.body;
74
 
75
+ if (!init_data) return res.status(401).json({ error: 'Unauthorized: init_data is missing' });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
+ try {
78
+ const botToken = process.env.BOT_TOKEN;
79
+ if (!botToken) return res.status(500).json({ error: 'Server configuration error' });
 
 
80
 
81
+ const urlParams = new URLSearchParams(init_data);
82
+ const hash = urlParams.get('hash');
83
+ urlParams.delete('hash');
84
 
85
+ const dataToCheck = [...urlParams.entries()]
86
+ .map(([key, value]) => `${key}=${value}`)
87
+ .sort()
88
+ .join('\n');
89
 
90
+ const secretKey = crypto.createHmac('sha256', 'WebAppData').update(botToken).digest();
91
+ const calculatedHash = crypto.createHmac('sha256', secretKey).update(dataToCheck).digest('hex');
 
92
 
93
+ if (calculatedHash !== hash) {
94
+ return res.status(403).json({ error: 'Forbidden: Invalid Telegram signature' });
95
+ }
 
96
 
97
+ const tgUser = JSON.parse(urlParams.get('user'));
 
98
 
99
+ if (String(tgUser.id) !== String(user_id)) {
100
+ return res.status(403).json({ error: 'Forbidden: User ID mismatch' });
101
+ }
102
 
103
+ const tgFullName = tgUser.last_name ? `${tgUser.first_name} ${tgUser.last_name}`.trim() : tgUser.first_name;
104
+ if (String(tgFullName) !== String(name) && String(tgUser.first_name) !== String(name)) {
105
+ return res.status(403).json({ error: 'Forbidden: Name mismatch' });
106
+ }
107
 
108
+ next();
109
+ } catch (error) {
110
+ return res.status(500).json({ error: 'Internal server error during validation' });
111
  }
112
+ };
113
 
114
+ // ==========================================
115
+ // ৫. API: ক্রিয়েট অ্যাকাউন্ট (/creataccoumt)
116
+ // ==========================================
117
+ app.post('/creataccoumt', checkPostMethod, verifyTelegramAuth, async (req, res) => {
118
+ const { user_id, refer_id, name, username, profile_pic_url } = req.body;
119
 
120
+ try {
121
+ const userRef = db1.ref('user').child(user_id);
122
+ const snapshot = await userRef.once('value');
 
 
 
123
 
124
+ if (snapshot.exists()) {
125
+ return res.status(200).json({ message: 'Account already exists. No action taken.' });
126
+ }
 
 
127
 
128
+ const newUserData = {
129
+ user_id,
130
+ refer_id: refer_id || null,
131
+ name: name || null,
132
+ username: username || null,
133
+ profile_pic_url: profile_pic_url || null,
134
+ balance: 0,
135
+ total_withdraw: 0,
136
+ total_withdraw_amount: 0,
137
+ join_date: admin.database.ServerValue.TIMESTAMP,
138
+ total_refer: 0
139
+ };
140
+
141
+ await userRef.set(newUserData);
142
+
143
+ if (refer_id) {
144
+ const referUserRef = db1.ref('user').child(refer_id);
145
+ const referUserSnap = await referUserRef.once('value');
146
+
147
+ if (referUserSnap.exists()) {
148
+ await referUserRef.child('total_refer').transaction((currentValue) => {
149
+ return (currentValue || 0) + 1;
150
+ });
151
+
152
+ const referListRef = db3.ref('refer').child(refer_id);
153
+ await referListRef.push(user_id);
154
+ }
155
+ }
156
 
157
+ res.status(201).json({ message: 'Account created successfully!' });
158
+ } catch (error) {
159
+ res.status(500).json({ error: 'Internal Server Error' });
160
  }
161
+ });
162
 
163
+ // ==========================================
164
+ // ৬. API: উইথড্র মেইন ব্যালেন্স (/withdraw-main)
165
+ // ==========================================
166
+ app.post('/withdraw-main', checkPostMethod, verifyTelegramAuth, async (req, res) => {
167
+ const { user_id, method, address, time, amount } = req.body;
168
+ const allowedMethods = ['bkash', 'mobile-gp', 'mobile-ar', 'mobile-ro', 'mobile-bl', 'mobile-tk', 'nagad', 'binance', 'usdt', 'ton'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
 
170
+ if (!method || !address || !amount) return res.status(400).json({ error: 'Missing required fields' });
171
+ if (!allowedMethods.includes(method)) return res.status(400).json({ error: 'Invalid withdrawal method' });
 
 
 
 
172
 
173
+ try {
174
+ const userRef = db1.ref('user').child(user_id);
175
+ const snapshot = await userRef.once('value');
 
 
 
176
 
177
+ if (!snapshot.exists()) return res.status(404).json({ error: 'User not found' });
 
178
 
179
+ const userData = snapshot.val();
180
+ const currentBalance = Number(userData.balance || 0);
181
+ const requestAmount = Number(amount);
182
 
183
+ if (currentBalance < requestAmount) {
184
+ return res.status(400).json({ error: 'Insufficient balance' });
185
+ }
186
 
187
+ await userRef.child('balance').set(currentBalance - requestAmount);
188
+
189
+ const pendingRef = db3.ref('withdrow/painding').child(user_id);
190
+ await pendingRef.push({
191
+ method,
192
+ address,
193
+ time: time || admin.database.ServerValue.TIMESTAMP,
194
+ amount: requestAmount,
195
+ status: 'pending'
196
+ });
197
 
198
+ res.status(200).json({ message: 'Withdrawal request successful' });
199
+ } catch (error) {
200
+ res.status(500).json({ error: 'Internal Server Error' });
201
  }
202
+ });
203
 
204
+ // ==========================================
205
+ // ৭. API: অ্যাড ব্যালেন্স উইথড্র (Admin 4 -> Admin 1)
206
+ // ==========================================
207
+ const adWithdrawPaths = [
208
+ '/withdraw-link-visit',
209
+ '/withdraw-adsgram-1',
210
+ '/withdraw-adsgram-2',
211
+ '/withdraw-gigapub-1',
212
+ '/withdraw-gigapub-2',
213
+ '/withdraw-monetag-1',
214
+ '/withdraw-monetag-2'
215
+ ];
216
+
217
+ app.post(adWithdrawPaths, checkPostMethod, async (req, res) => {
218
+ const { user_id, amount, method } = req.body;
219
+
220
+ if (!user_id || !amount || method !== 'wallet') {
221
+ return res.status(400).json({ error: 'Invalid request. Method must be wallet and amount is required.' });
222
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
+ const adNetworkName = req.path.replace('/withdraw-', '');
225
+ const requestAmount = Number(amount);
226
 
227
+ try {
228
+ const adRef = db4.ref(adNetworkName).child(user_id);
229
+ const adSnapshot = await adRef.once('value');
230
 
231
+ if (!adSnapshot.exists()) return res.status(404).json({ error: 'No ad earnings found for this user' });
232
 
233
+ let adCurrentBalance = Number(adSnapshot.val().balance || 0);
234
 
235
+ if (adCurrentBalance < requestAmount) {
236
+ return res.status(400).json({ error: 'Insufficient ad balance' });
237
+ }
238
 
239
+ await adRef.child('balance').set(adCurrentBalance - requestAmount);
240
 
241
+ const mainUserRef = db1.ref('user').child(user_id);
242
+ await mainUserRef.child('balance').transaction((currentMainBalance) => {
243
+ return (currentMainBalance || 0) + requestAmount;
244
+ });
245
 
246
+ res.status(200).json({ message: `Success! ${requestAmount} transferred to main balance from ${adNetworkName}` });
247
+ } catch (error) {
248
+ res.status(500).json({ error: 'Internal Server Error' });
249
+ }
250
+ });
 
251
 
252
+ // সার্ভার স্টার্ট (প্রতিটি ওয়ার্কার এই পোর্টে রিকোয়েস্ট শেয়ার করবে)
253
+ const PORT = process.env.PORT || 7860;
254
+ app.listen(PORT);
255
+ }