Shinhati2023 commited on
Commit
f5d39ec
·
verified ·
1 Parent(s): b7da921

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +83 -67
server.js CHANGED
@@ -20,7 +20,6 @@ cloudinary.config({
20
  const DB_FILE = 'megapin_master_db.json';
21
  const MAX_TRENDING = 100;
22
  const ADMIN_USER = process.env.ADMIN_USER;
23
- // Admin Pass is checked in /login via process.env.ADMIN_PASS
24
  const DEFAULT_AVATAR = "https://cdn-icons-png.flaticon.com/512/149/149071.png";
25
 
26
  let localDB = null;
@@ -28,7 +27,6 @@ let localDB = null;
28
  app.use(express.urlencoded({ extended: true }));
29
  app.use(express.json());
30
  app.set('view engine', 'ejs');
31
- app.use(express.static('public')); // ADDED: To serve your external script/css
32
 
33
  app.use(cookieSession({
34
  name: '__Secure-session',
@@ -73,19 +71,22 @@ const uploadImage = (buffer) => {
73
  });
74
  };
75
 
 
76
  function addNotification(toUser, fromUser, type, pinId = null, preview = "") {
77
  if (toUser === fromUser) return;
78
  if (!localDB.users[toUser]) return;
79
  if (!localDB.users[toUser].notifications) localDB.users[toUser].notifications = [];
 
80
  localDB.users[toUser].notifications.unshift({
81
  from: fromUser,
82
  fromAvatar: localDB.users[fromUser].avatar,
83
- type: type,
84
  pinId: pinId,
85
  preview: preview,
86
  timestamp: Date.now(),
87
  read: false
88
  });
 
89
  if (localDB.users[toUser].notifications.length > 50) localDB.users[toUser].notifications.pop();
90
  }
91
 
@@ -108,7 +109,7 @@ function checkAdmin(req, res, next) {
108
 
109
  // --- ROUTES ---
110
 
111
- // Helper to format pins for view
112
  function formatPins(pins, username) {
113
  return pins.map(pin => {
114
  const authorData = localDB.users[pin.author] || { avatar: DEFAULT_AVATAR, displayName: pin.author };
@@ -124,6 +125,7 @@ function formatPins(pins, username) {
124
  });
125
  }
126
 
 
127
  app.get('/', async (req, res) => {
128
  await initDB();
129
  const username = req.session.user;
@@ -138,23 +140,32 @@ app.get('/', async (req, res) => {
138
  if (currentUser.notifications) notifications = currentUser.notifications;
139
  }
140
 
141
- // Default View: All Pins
142
- let viewPins = formatPins(localDB.pins, username);
 
 
 
 
 
 
 
 
143
 
144
  res.render('index', {
145
- pins: viewPins,
146
  user: currentUser,
147
  notifications,
148
  isAdmin: (username === ADMIN_USER),
 
149
  pageType: 'home',
150
  profileUser: null
151
  });
152
  });
153
 
154
- // Profile Route
155
  app.get('/u/:username', async (req, res) => {
156
  await initDB();
157
- const username = req.session.user; // My logged in session
158
  const targetUsername = req.params.username;
159
 
160
  if (!localDB.users[targetUsername]) return res.redirect('/');
@@ -163,7 +174,6 @@ app.get('/u/:username', async (req, res) => {
163
  const userPins = localDB.pins.filter(p => p.author === targetUsername);
164
  const formattedPins = formatPins(userPins, username);
165
 
166
- // Construct Profile Object
167
  const profileUser = {
168
  username: targetUsername,
169
  ...targetUser,
@@ -188,7 +198,14 @@ app.get('/u/:username', async (req, res) => {
188
 
189
  // --- API ACTIONS ---
190
 
191
- // Search User API
 
 
 
 
 
 
 
192
  app.get('/api/search-users', async (req, res) => {
193
  await initDB();
194
  const q = req.query.q ? req.query.q.toLowerCase() : '';
@@ -201,58 +218,6 @@ app.get('/api/search-users', async (req, res) => {
201
  res.json(results);
202
  });
203
 
204
- // Get Single Pin Details (For Modal)
205
- app.get('/api/pin/:id', async (req, res) => {
206
- await initDB();
207
- const pin = localDB.pins.find(p => p.id === parseInt(req.params.id));
208
- if(!pin) return res.json({error: "Not found"});
209
- const formatted = formatPins([pin], req.session.user)[0];
210
- res.json(formatted);
211
- });
212
-
213
- // ADMIN ROUTES
214
- app.post('/api/admin/badge', checkAdmin, async (req, res) => {
215
- await initDB();
216
- const { targetUser, badge } = req.body; // badge: 'blue', 'green', or ''
217
- if(localDB.users[targetUser]) {
218
- localDB.users[targetUser].badge = badge;
219
- await saveDB();
220
- res.json({success: true});
221
- } else {
222
- res.json({success: false});
223
- }
224
- });
225
-
226
- app.post('/api/admin/ban', checkAdmin, async (req, res) => {
227
- await initDB();
228
- const { targetUser, banned } = req.body;
229
- if(localDB.users[targetUser] && targetUser !== ADMIN_USER) {
230
- localDB.users[targetUser].banned = banned; // true or false
231
- await saveDB();
232
- res.json({success: true});
233
- } else {
234
- res.json({success: false});
235
- }
236
- });
237
-
238
- app.post('/api/admin/delete-user', checkAdmin, async (req, res) => {
239
- await initDB();
240
- const { targetUser } = req.body;
241
- if(localDB.users[targetUser] && targetUser !== ADMIN_USER) {
242
- delete localDB.users[targetUser];
243
- // Clean up their pins
244
- localDB.pins = localDB.pins.filter(p => p.author !== targetUser);
245
- await saveDB();
246
- res.json({success: true});
247
- } else {
248
- res.json({success: false});
249
- }
250
- });
251
-
252
- // (Keep existing API routes: like, follow, comment, clear-notifications, signup, login, etc.)
253
- // ... [INSERT YOUR EXISTING /api/like, /api/follow routes HERE] ...
254
- // Re-pasting essential ones for context:
255
-
256
  app.post('/api/like', checkBan, async (req, res) => {
257
  if (!req.session.user) return res.status(401).json({error: "Login required"});
258
  await initDB();
@@ -281,12 +246,16 @@ app.post('/api/follow', checkBan, async (req, res) => {
281
  const { targetUser } = req.body;
282
  const me = req.session.user;
283
  if (!localDB.users[targetUser] || targetUser === me) return res.json({ success: false });
 
284
  const targetData = localDB.users[targetUser];
285
  const myData = localDB.users[me];
 
286
  if (!targetData.followers) targetData.followers = [];
287
  if (!myData.following) myData.following = [];
 
288
  let isFollowing = false;
289
  const idx = targetData.followers.indexOf(me);
 
290
  if (idx === -1) {
291
  targetData.followers.push(me);
292
  myData.following.push(targetUser);
@@ -323,6 +292,55 @@ app.post('/api/comment', checkBan, async (req, res) => {
323
  res.json({ success: false });
324
  });
325
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  app.post('/signup', async (req, res) => {
327
  const { username, password, email } = req.body;
328
  await initDB();
@@ -345,14 +363,13 @@ app.post('/signup', async (req, res) => {
345
  app.post('/login', async (req, res) => {
346
  const { username, password } = req.body;
347
  await initDB();
348
- // Admin Check
349
  if (username === ADMIN_USER && password === process.env.ADMIN_PASS) {
350
  req.session.user = username;
351
  return res.redirect('/');
352
  }
353
  const user = localDB.users[username];
354
  if (user && bcrypt.compareSync(password, user.hash)) {
355
- if(user.banned) return res.send("Account Suspended.");
356
  req.session.user = username;
357
  res.redirect('/');
358
  } else {
@@ -389,7 +406,6 @@ app.post('/update-profile', upload.single('avatar'), checkBan, async (req, res)
389
  user.avatar = result.secure_url;
390
  }
391
  await saveDB();
392
- // Redirect back to profile page
393
  res.redirect('/u/' + req.session.user);
394
  });
395
 
@@ -408,4 +424,4 @@ app.post('/delete', checkBan, async (req, res) => {
408
  app.get('/logout', (req, res) => { req.session = null; res.redirect('/'); });
409
 
410
  initDB();
411
- app.listen(7860, () => console.log("Megapin 2.0 Active"));
 
20
  const DB_FILE = 'megapin_master_db.json';
21
  const MAX_TRENDING = 100;
22
  const ADMIN_USER = process.env.ADMIN_USER;
 
23
  const DEFAULT_AVATAR = "https://cdn-icons-png.flaticon.com/512/149/149071.png";
24
 
25
  let localDB = null;
 
27
  app.use(express.urlencoded({ extended: true }));
28
  app.use(express.json());
29
  app.set('view engine', 'ejs');
 
30
 
31
  app.use(cookieSession({
32
  name: '__Secure-session',
 
71
  });
72
  };
73
 
74
+ // --- LOGIC HELPERS ---
75
  function addNotification(toUser, fromUser, type, pinId = null, preview = "") {
76
  if (toUser === fromUser) return;
77
  if (!localDB.users[toUser]) return;
78
  if (!localDB.users[toUser].notifications) localDB.users[toUser].notifications = [];
79
+
80
  localDB.users[toUser].notifications.unshift({
81
  from: fromUser,
82
  fromAvatar: localDB.users[fromUser].avatar,
83
+ type: type,
84
  pinId: pinId,
85
  preview: preview,
86
  timestamp: Date.now(),
87
  read: false
88
  });
89
+
90
  if (localDB.users[toUser].notifications.length > 50) localDB.users[toUser].notifications.pop();
91
  }
92
 
 
109
 
110
  // --- ROUTES ---
111
 
112
+ // Helper: Format pins for view
113
  function formatPins(pins, username) {
114
  return pins.map(pin => {
115
  const authorData = localDB.users[pin.author] || { avatar: DEFAULT_AVATAR, displayName: pin.author };
 
125
  });
126
  }
127
 
128
+ // HOME PAGE
129
  app.get('/', async (req, res) => {
130
  await initDB();
131
  const username = req.session.user;
 
140
  if (currentUser.notifications) notifications = currentUser.notifications;
141
  }
142
 
143
+ let viewPins = localDB.pins;
144
+ if (req.query.q) {
145
+ const q = req.query.q.toLowerCase();
146
+ viewPins = localDB.pins.filter(p =>
147
+ p.author.toLowerCase().includes(q) ||
148
+ (p.caption && p.caption.toLowerCase().includes(q))
149
+ );
150
+ }
151
+
152
+ const formattedPins = formatPins(viewPins, username);
153
 
154
  res.render('index', {
155
+ pins: formattedPins,
156
  user: currentUser,
157
  notifications,
158
  isAdmin: (username === ADMIN_USER),
159
+ searchQuery: req.query.q || '',
160
  pageType: 'home',
161
  profileUser: null
162
  });
163
  });
164
 
165
+ // PROFILE PAGE
166
  app.get('/u/:username', async (req, res) => {
167
  await initDB();
168
+ const username = req.session.user;
169
  const targetUsername = req.params.username;
170
 
171
  if (!localDB.users[targetUsername]) return res.redirect('/');
 
174
  const userPins = localDB.pins.filter(p => p.author === targetUsername);
175
  const formattedPins = formatPins(userPins, username);
176
 
 
177
  const profileUser = {
178
  username: targetUsername,
179
  ...targetUser,
 
198
 
199
  // --- API ACTIONS ---
200
 
201
+ app.get('/api/pin/:id', async (req, res) => {
202
+ await initDB();
203
+ const pin = localDB.pins.find(p => p.id === parseInt(req.params.id));
204
+ if(!pin) return res.json({error: "Not found"});
205
+ const formatted = formatPins([pin], req.session.user)[0];
206
+ res.json(formatted);
207
+ });
208
+
209
  app.get('/api/search-users', async (req, res) => {
210
  await initDB();
211
  const q = req.query.q ? req.query.q.toLowerCase() : '';
 
218
  res.json(results);
219
  });
220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  app.post('/api/like', checkBan, async (req, res) => {
222
  if (!req.session.user) return res.status(401).json({error: "Login required"});
223
  await initDB();
 
246
  const { targetUser } = req.body;
247
  const me = req.session.user;
248
  if (!localDB.users[targetUser] || targetUser === me) return res.json({ success: false });
249
+
250
  const targetData = localDB.users[targetUser];
251
  const myData = localDB.users[me];
252
+
253
  if (!targetData.followers) targetData.followers = [];
254
  if (!myData.following) myData.following = [];
255
+
256
  let isFollowing = false;
257
  const idx = targetData.followers.indexOf(me);
258
+
259
  if (idx === -1) {
260
  targetData.followers.push(me);
261
  myData.following.push(targetUser);
 
292
  res.json({ success: false });
293
  });
294
 
295
+ app.post('/api/clear-notifications', async (req, res) => {
296
+ if (!req.session.user) return;
297
+ await initDB();
298
+ if(localDB.users[req.session.user]) {
299
+ localDB.users[req.session.user].notifications = [];
300
+ await saveDB();
301
+ }
302
+ res.json({success: true});
303
+ });
304
+
305
+ // --- ADMIN API ---
306
+ app.post('/api/admin/badge', checkAdmin, async (req, res) => {
307
+ await initDB();
308
+ const { targetUser, badge } = req.body;
309
+ if(localDB.users[targetUser]) {
310
+ localDB.users[targetUser].badge = badge;
311
+ await saveDB();
312
+ res.json({success: true});
313
+ } else {
314
+ res.json({success: false});
315
+ }
316
+ });
317
+
318
+ app.post('/api/admin/ban', checkAdmin, async (req, res) => {
319
+ await initDB();
320
+ const { targetUser, banned } = req.body;
321
+ if(localDB.users[targetUser] && targetUser !== ADMIN_USER) {
322
+ localDB.users[targetUser].banned = banned;
323
+ await saveDB();
324
+ res.json({success: true});
325
+ } else {
326
+ res.json({success: false});
327
+ }
328
+ });
329
+
330
+ app.post('/api/admin/delete-user', checkAdmin, async (req, res) => {
331
+ await initDB();
332
+ const { targetUser } = req.body;
333
+ if(localDB.users[targetUser] && targetUser !== ADMIN_USER) {
334
+ delete localDB.users[targetUser];
335
+ localDB.pins = localDB.pins.filter(p => p.author !== targetUser);
336
+ await saveDB();
337
+ res.json({success: true});
338
+ } else {
339
+ res.json({success: false});
340
+ }
341
+ });
342
+
343
+ // --- STANDARD FORMS ---
344
  app.post('/signup', async (req, res) => {
345
  const { username, password, email } = req.body;
346
  await initDB();
 
363
  app.post('/login', async (req, res) => {
364
  const { username, password } = req.body;
365
  await initDB();
 
366
  if (username === ADMIN_USER && password === process.env.ADMIN_PASS) {
367
  req.session.user = username;
368
  return res.redirect('/');
369
  }
370
  const user = localDB.users[username];
371
  if (user && bcrypt.compareSync(password, user.hash)) {
372
+ if(user.banned) return res.send("Banned.");
373
  req.session.user = username;
374
  res.redirect('/');
375
  } else {
 
406
  user.avatar = result.secure_url;
407
  }
408
  await saveDB();
 
409
  res.redirect('/u/' + req.session.user);
410
  });
411
 
 
424
  app.get('/logout', (req, res) => { req.session = null; res.redirect('/'); });
425
 
426
  initDB();
427
+ app.listen(7860, () => console.log("Megapin Redux Active"));