HerzaJ commited on
Commit
11b4f0e
·
verified ·
1 Parent(s): 3cb11cf

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +1057 -1062
index.js CHANGED
@@ -793,290 +793,289 @@ app.post('/api/auth/register', checkBanned, authRateLimit, async (req, res) => {
793
  </div>
794
  </div>
795
  <div style="background: #f8f9fa; padding: 25px 30px; text-align: center; border-top: 1px solid #e9ecef;">
796
- <p style="color: #6c757d;
797
- margin: 0 0 10px 0; font-size: 14px;">
798
  Need help? Contact our support team
799
  </p>
800
  <p style="color: #adb5bd; margin: 0; font-size: 12px;">
801
  © 2025 DashX. All rights reserved.
802
  </p>
803
- </div>
804
- </div>
805
- </div>
806
- </body>
807
- </html>
808
- `;
809
-
810
- await transporter.sendMail({
811
- from: 'dashxapi@gmail.com',
812
- to: email,
813
- subject: 'DashX - Email Verification',
814
- html: emailTemplate
815
- });
816
-
817
- res.json({
818
- success: true,
819
- message: 'Verification code sent to your email. Please verify within 15 minutes.',
820
- expiresIn: '15 minutes'
821
- });
822
-
823
- } catch (error) {
824
- console.error('Registration error:', error);
825
- res.status(500).json({ success: false, error: 'Internal server error' });
826
- }
827
- });
828
-
829
- app.post('/api/auth/verify', checkBanned, authRateLimit, async (req, res) => {
830
- try {
831
- const { email, code } = req.body;
832
-
833
- if (!email || !code) {
834
- return res.status(400).json({
835
- success: false,
836
- error: 'Email and verification code are required'
837
- });
838
- }
839
 
840
- const pendingVerification = await PendingVerification.findOne({
841
- email,
842
- verificationCode: code
843
- });
 
844
 
845
- if (!pendingVerification) {
846
- return res.status(400).json({
847
- success: false,
848
- error: 'Invalid verification code or code has expired'
849
- });
850
- }
851
 
852
- const existingUser = await User.findOne({
853
- $or: [{ email: pendingVerification.email }, { username: pendingVerification.username }]
854
- });
855
 
856
- if (existingUser) {
857
- await PendingVerification.deleteOne({ _id: pendingVerification._id });
858
- return res.status(400).json({
859
- success: false,
860
- error: 'User already exists in database'
861
- });
862
- }
863
-
864
- const apikey = generateApiKey();
865
-
866
- const user = new User({
867
- username: pendingVerification.username,
868
- email: pendingVerification.email,
869
- password: pendingVerification.password,
870
- apikey: apikey,
871
- profileUrl: 'https://files.catbox.moe/8l6hhm',
872
- verified: true,
873
- ipAddress: pendingVerification.ipAddress,
874
- role: 'user',
875
- premium: false,
876
- limit: 30,
877
- requests: 0,
878
- requestsToday: 0,
879
- lastReset: new Date(),
880
- banned: false
881
- });
882
-
883
- await user.save();
884
- await PendingVerification.deleteOne({ _id: pendingVerification._id });
885
-
886
- await logActivity(user._id, user.username, 'api_key_generated', 'Account created and verified successfully', {
887
- apikey: user.apikey,
888
- registrationIP: pendingVerification.ipAddress
889
- });
890
-
891
- const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '30d' });
892
-
893
- res.json({
894
- success: true,
895
- token,
896
- user: {
897
- id: user._id,
898
- username: user.username,
899
- email: user.email,
900
- apikey: user.apikey,
901
- profileUrl: user.profileUrl,
902
- premium: user.premium,
903
- limit: user.limit
904
- },
905
- message: 'Account created and verified successfully!'
906
- });
907
-
908
- } catch (error) {
909
- console.error('Verification error:', error);
910
- res.status(500).json({ success: false, error: 'Internal server error' });
911
- }
912
- });
913
-
914
- app.get('/api/admin/search-users', authenticate, async (req, res) => {
915
- try {
916
- if (req.user.role !== 'admin') {
917
- return res.status(403).json({ success: false, error: 'Admin access required' });
918
- }
919
-
920
- const { query } = req.query;
921
- if (!query) {
922
- return res.json({ success: true, users: [] });
923
- }
924
-
925
- const users = await User.find({
926
- $or: [
927
- { username: { $regex: query, $options: 'i' } },
928
- { email: { $regex: query, $options: 'i' } }
929
- ],
930
- role: { $ne: 'admin' }
931
- }).limit(10).select('username email limit premium role');
932
-
933
- res.json({ success: true, users });
934
- } catch (error) {
935
- console.error('Search users error:', error);
936
- res.status(500).json({ success: false, error: 'Internal server error' });
937
- }
938
- });
939
-
940
- app.get('/api/admin/user-role/:userId', authenticate, async (req, res) => {
941
- try {
942
- if (req.user.role !== 'admin') {
943
- return res.status(403).json({ success: false, error: 'Admin access required' });
944
- }
945
-
946
- const userRole = await UserRole.findOne({ userId: req.params.userId });
947
- res.json({ success: true, role: userRole });
948
- } catch (error) {
949
- res.status(500).json({ success: false, error: 'Internal server error' });
950
- }
951
- });
952
-
953
- app.post('/api/auth/login', checkBanned, authRateLimit, async (req, res) => {
954
- try {
955
- const { email, password } = req.body;
956
-
957
- if (!email || !password) {
958
- return res.status(400).json({
959
- success: false,
960
- error: 'Email and password are required'
961
- });
962
- }
963
-
964
- const user = await User.findOne({ email });
965
- if (!user) {
966
- return res.status(400).json({ success: false, error: 'Invalid credentials' });
967
- }
968
-
969
- const isValidPassword = await bcrypt.compare(password, user.password);
970
- if (!isValidPassword) {
971
- return res.status(400).json({ success: false, error: 'Invalid credentials' });
972
- }
973
-
974
- if (user.banned) {
975
- return res.status(403).json({ success: false, error: 'Account is permanently banned' });
976
- }
977
-
978
- await checkPremiumExpiry(user);
979
- await checkRoleExpiry(user);
980
- await resetUserLimitIfNeeded(user);
981
-
982
- const isTempBanned = await checkTempBan(user);
983
- if (isTempBanned) {
984
- const banUntil = new Date(user.tempBanUntil);
985
- return res.status(403).json({
986
- success: false,
987
- error: `Account temporarily banned until ${banUntil.toLocaleString()}. Reason: ${user.tempBanReason || 'No reason provided'}`
988
- });
989
- }
990
-
991
- const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '30d' });
992
-
993
- res.json({
994
- success: true,
995
- token,
996
- user: {
997
- id: user._id,
998
- username: user.username,
999
- email: user.email,
1000
- apikey: user.apikey,
1001
- profileUrl: user.profileUrl,
1002
- premium: user.premium,
1003
- premiumExpiredAt: user.premiumExpiredAt,
1004
- limit: user.limit,
1005
- role: user.role
1006
- }
1007
- });
1008
- } catch (error) {
1009
- console.error('Login error:', error);
1010
- res.status(500).json({ success: false, error: 'Internal server error' });
1011
- }
1012
- });
1013
-
1014
- app.post('/api/auth/admin-login', checkBanned, authRateLimit, async (req, res) => {
1015
- try {
1016
- const { username, password } = req.body;
1017
-
1018
- if (username === 'HERXA' && password === 'BTXHZ') {
1019
- let admin = await User.findOne({ username: 'HERXA' });
1020
- if (!admin) {
1021
- admin = new User({
1022
- username: 'HERXA',
1023
- email: 'admin@dashx.com',
1024
- password: await bcrypt.hash('BTXHZ', 12),
1025
- apikey: 'DHX-M3SA',
1026
- profileUrl: 'https://files.catbox.moe/8l6hhm',
1027
- verified: true,
1028
- role: 'admin',
1029
- premium: true,
1030
- limit: 9999,
1031
- ipAddress: req.realIP
1032
- });
1033
- await admin.save();
1034
- } else {
1035
- admin.apikey = 'DHX-M3SA';
1036
- admin.limit = 9999;
1037
- admin.role = 'admin';
1038
- admin.premium = true;
1039
- await admin.save();
1040
- }
1041
-
1042
- const token = jwt.sign({ userId: admin._id }, JWT_SECRET, { expiresIn: '30d' });
1043
- return res.json({
1044
- success: true,
1045
- token,
1046
- user: {
1047
- id: admin._id,
1048
- username: admin.username,
1049
- role: admin.role,
1050
- apikey: admin.apikey,
1051
- profileUrl: admin.profileUrl,
1052
- limit: admin.limit
1053
- }
1054
- });
1055
- }
1056
-
1057
- const admin = await User.findOne({ username, role: 'admin' });
1058
- if (!admin || !await bcrypt.compare(password, admin.password)) {
1059
- return res.status(400).json({ success: false, error: 'Invalid admin credentials' });
1060
- }
1061
-
1062
- const token = jwt.sign({ userId: admin._id }, JWT_SECRET, { expiresIn: '30d' });
1063
- res.json({
1064
- success: true,
1065
- token,
1066
- user: {
1067
- id: admin._id,
1068
- username: admin.username,
1069
- role: admin.role,
1070
- apikey: admin.apikey,
1071
- profileUrl: admin.profileUrl,
1072
- limit: admin.limit
1073
- }
1074
- });
1075
- } catch (error) {
1076
- console.error('Admin login error:', error);
1077
- res.status(500).json({ success: false, error: 'Internal server error' });
1078
- }
1079
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1080
 
1081
  app.get('/api/user/profile', authenticate, async (req, res) => {
1082
  try {
@@ -1136,45 +1135,44 @@ app.get('/api/user/profile', authenticate, async (req, res) => {
1136
  }
1137
  });
1138
 
1139
- app.get('/api/user/activities', authenticate, async (req, res) => {
1140
- try {
1141
- const activities = await Activity.find({ userId: req.user._id })
1142
- .sort({ timestamp: -1 })
1143
- .limit(50);
1144
-
1145
- const requestLogs = await RequestLog.find({ userId: req.user._id })
1146
- .sort({ timestamp: -1 })
1147
- .limit(20);
1148
-
1149
- res.json({
1150
- success: true,
1151
- activities: activities.map(activity => ({
1152
- type: activity.type,
1153
- description: activity.description,
1154
- timestamp: activity.timestamp,
1155
- timeAgo: getTimeAgo(activity.timestamp),
1156
- metadata: activity.metadata
1157
- })),
1158
- requestLogs: requestLogs.map(log => ({
1159
- endpoint: log.endpoint,
1160
- timestamp: log.timestamp,
1161
- timeAgo: getTimeAgo(log.timestamp),
1162
- success: log.success,
1163
- ipAddress: log.ipAddress,
1164
- limitDeducted: log.limitDeducted
1165
- }))
1166
- });
1167
- } catch (error) {
1168
- console.error('Activities fetch error:', error);
1169
- res.status(500).json({ success: false, error: 'Internal server error' });
1170
- }
1171
- });
1172
-
1173
- app.get('/api/user/usage-stats', authenticate, async (req, res) => {
1174
  try {
1175
  const userId = req.user._id.toString();
1176
 
1177
- // Hitung request hari ini untuk user ini
1178
  const todayStart = new Date();
1179
  todayStart.setHours(0, 0, 0, 0);
1180
 
@@ -1183,7 +1181,6 @@ app.get('/api/user/profile', authenticate, async (req, res) => {
1183
  timestamp: { $gte: todayStart }
1184
  });
1185
 
1186
- // Hitung total request untuk user ini
1187
  const userTotalRequests = await RequestLog.countDocuments({
1188
  userId
1189
  });
@@ -1247,79 +1244,79 @@ app.get('/api/user/profile', authenticate, async (req, res) => {
1247
  }
1248
  });
1249
 
1250
- app.put('/api/user/profile', authenticate, async (req, res) => {
1251
- try {
1252
- const { username, profileUrl, customApiKey } = req.body;
1253
- let updated = false;
1254
-
1255
- if (username && username !== req.user.username) {
1256
- const existing = await User.findOne({ username });
1257
- if (existing) {
1258
- return res.status(400).json({ success: false, error: 'Username already taken' });
1259
- }
1260
-
1261
- const oldUsername = req.user.username;
1262
- req.user.username = username;
1263
- updated = true;
1264
-
1265
- await logActivity(req.user._id, req.user.username, 'profile_updated', `Username changed from ${oldUsername} to ${username}`, {
1266
- oldUsername,
1267
- newUsername: username
1268
- });
1269
- }
1270
-
1271
- if (profileUrl !== undefined && profileUrl !== req.user.profileUrl) {
1272
- req.user.profileUrl = profileUrl;
1273
- updated = true;
1274
-
1275
- await logActivity(req.user._id, req.user.username, 'profile_updated', 'Profile URL updated', {
1276
- newProfileUrl: profileUrl
1277
- });
1278
- }
1279
-
1280
- if (customApiKey && (req.user.premium || req.user.role === 'admin')) {
1281
- const existing = await User.findOne({ apikey: customApiKey });
1282
- if (existing && existing._id.toString() !== req.user._id.toString()) {
1283
- return res.status(400).json({ success: false, error: 'API key already in use' });
1284
- }
1285
-
1286
- const oldApiKey = req.user.apikey;
1287
- req.user.apikey = customApiKey;
1288
- updated = true;
1289
-
1290
- await logActivity(req.user._id, req.user.username, 'api_key_updated', 'Custom API key set', {
1291
- oldApiKey,
1292
- newApiKey: customApiKey
1293
- });
1294
- }
1295
-
1296
- if (updated) {
1297
- await req.user.save();
1298
- }
1299
-
1300
- res.json({ success: true, message: 'Profile updated successfully' });
1301
- } catch (error) {
1302
- console.error('Profile update error:', error);
1303
- res.status(500).json({ success: false, error: 'Internal server error' });
1304
- }
1305
- });
1306
-
1307
- app.delete('/api/user/account', authenticate, async (req, res) => {
1308
- try {
1309
- if (req.user.role === 'admin') {
1310
- return res.status(403).json({ success: false, error: 'Cannot delete admin account' });
1311
- }
1312
-
1313
- await User.deleteOne({ _id: req.user._id });
1314
- await Activity.deleteMany({ userId: req.user._id });
1315
- res.json({ success: true, message: 'Account deleted successfully' });
1316
- } catch (error) {
1317
- console.error('Account deletion error:', error);
1318
- res.status(500).json({ success: false, error: 'Internal server error' });
1319
- }
1320
- });
1321
-
1322
- app.get('/api/stats/all', async (req, res) => {
1323
  try {
1324
  const totalUsers = await User.countDocuments();
1325
  const totalRequests = await RequestLog.countDocuments();
@@ -1426,692 +1423,690 @@ app.get('/api/user/profile', authenticate, async (req, res) => {
1426
  }
1427
  });
1428
 
1429
- app.post('/api/user/regenerate-key', authenticate, async (req, res) => {
1430
- try {
1431
- if (!req.user.premium && req.user.role !== 'admin') {
1432
- return res.status(403).json({ success: false, error: 'Premium feature only' });
1433
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1434
 
1435
- const oldApikey = req.user.apikey;
 
 
 
 
 
1436
 
1437
- if (req.user.role === 'admin') {
1438
- req.user.apikey = 'DHX-M3SA';
1439
- } else {
1440
- req.user.apikey = generateApiKey();
1441
- }
1442
 
1443
- await req.user.save();
 
 
 
 
 
1444
 
1445
- await logActivity(req.user._id, req.user.username, 'api_key_generated', 'API key regenerated', {
1446
- oldApikey,
1447
- newApikey: req.user.apikey
1448
- });
 
 
1449
 
1450
- res.json({ success: true, apikey: req.user.apikey });
1451
- } catch (error) {
1452
- console.error('API key regeneration error:', error);
1453
- res.status(500).json({ success: false, error: 'Internal server error' });
1454
- }
1455
- });
1456
 
1457
- app.post('/api/user/redeem', authenticate, async (req, res) => {
1458
- try {
1459
- const { code } = req.body;
1460
 
1461
- if (!code) {
1462
- return res.status(400).json({
1463
- success: false,
1464
- error: 'Redeem code is required'
1465
- });
1466
- }
1467
 
1468
- const redeemCode = await RedeemCode.findOne({ code });
 
 
 
 
1469
 
1470
- if (!redeemCode) {
1471
- return res.status(400).json({
1472
- success: false,
1473
- error: 'This redeem code is not available anymore or never exist'
1474
- });
1475
- }
1476
 
1477
- if (redeemCode.used) {
1478
- return res.status(400).json({
1479
- success: false,
1480
- error: 'This redeem code has already been used'
1481
- });
1482
- }
1483
 
1484
- if (new Date() > redeemCode.codeExpired) {
1485
- return res.status(400).json({
1486
- success: false,
1487
- error: 'This redeem code is not available anymore or never exist'
1488
- });
1489
- }
1490
-
1491
- let benefits = [];
1492
-
1493
- if (redeemCode.type === 'limit' || redeemCode.type === 'both') {
1494
- req.user.limit += redeemCode.limitValue;
1495
- benefits.push(`+${redeemCode.limitValue} API requests`);
1496
- }
1497
-
1498
- if (redeemCode.type === 'premium' || redeemCode.type === 'both') {
1499
- req.user.premium = true;
1500
- req.user.premiumExpiredAt = redeemCode.premiumExpired;
1501
- benefits.push(`Premium activated until ${redeemCode.premiumExpired.toLocaleString()}`);
1502
- }
1503
-
1504
- if (redeemCode.type === 'premium' && redeemCode.limitValue > 0) {
1505
- req.user.limit += redeemCode.limitValue;
1506
- benefits.push(`+${redeemCode.limitValue} API requests (bonus)`);
1507
- }
1508
-
1509
- redeemCode.used = true;
1510
- redeemCode.usedBy = req.user.username;
1511
-
1512
- await req.user.save();
1513
- await redeemCode.save();
1514
-
1515
- await logActivity(req.user._id, req.user.username, 'redeem_code_used', `Redeem code used: ${benefits.join(', ')}`, {
1516
- code: code,
1517
- type: redeemCode.type,
1518
- benefits
1519
- });
1520
-
1521
- res.json({
1522
- success: true,
1523
- message: 'Redeem code used successfully',
1524
- benefits
1525
- });
1526
- } catch (error) {
1527
- console.error('Redeem code error:', error);
1528
- res.status(500).json({ success: false, error: 'Internal server error' });
1529
- }
1530
- });
1531
-
1532
- app.get('/api/admin/stats', authenticate, async (req, res) => {
1533
- try {
1534
- if (req.user.role !== 'admin') {
1535
- return res.status(403).json({ success: false, error: 'Admin access required' });
1536
- }
1537
-
1538
- const totalUsers = await User.countDocuments();
1539
- const pendingUsers = await PendingVerification.countDocuments();
1540
- const totalRequests = await RequestLog.countDocuments();
1541
-
1542
- const todayStart = new Date();
1543
- todayStart.setHours(0, 0, 0, 0);
1544
-
1545
- const todayRequests = await RequestLog.countDocuments({
1546
- timestamp: { $gte: todayStart }
1547
- });
1548
-
1549
- res.json({
1550
- success: true,
1551
- stats: {
1552
- totalUsers,
1553
- pendingUsers,
1554
- totalRequests,
1555
- todayRequests
1556
- }
1557
- });
1558
- } catch (error) {
1559
- console.error('Admin stats error:', error);
1560
- res.status(500).json({ success: false, error: 'Internal server error' });
1561
- }
1562
- });
1563
-
1564
- app.get('/api/server-stats', async (req, res) => {
1565
- try {
1566
-
1567
- const totalUsers = await User.countDocuments();
1568
- const regularUsers = await User.countDocuments({
1569
- $and: [
1570
- { premium: false },
1571
- { $or: [{ userRole: null }, { userRole: { $exists: false } }] }
1572
- ]
1573
- });
1574
- const premiumUsers = await User.countDocuments({ premium: true });
1575
-
1576
- const cheapCount = await User.countDocuments({ userRole: 'cheap' });
1577
- const premiumRoleCount = await User.countDocuments({ userRole: 'premium' });
1578
- const vipCount = await User.countDocuments({ userRole: 'vip' });
1579
- const supremeCount = await User.countDocuments({ userRole: 'supreme' });
1580
-
1581
- let dbSize = '0 MB';
1582
- let storageSize = '0 GB';
1583
-
1584
- try {
1585
- const dbStats = await mongoose.connection.db.stats();
1586
- dbSize = (dbStats.dataSize / 1024 / 1024).toFixed(2) + ' MB';
1587
- storageSize = (dbStats.storageSize / 1024 / 1024 / 1024).toFixed(2) + ' GB';
1588
- } catch (dbError) {
1589
- console.log('DB stats not available:', dbError.message);
1590
- }
1591
-
1592
- const memUsage = process.memoryUsage();
1593
- const ramUsage = (memUsage.heapUsed / 1024 / 1024).toFixed(2) + ' MB';
1594
-
1595
- const cpuUsage = process.cpuUsage();
1596
- const cpuPercent = ((cpuUsage.user + cpuUsage.system) / 1000000).toFixed(2);
1597
-
1598
- res.json({
1599
- success: true,
1600
- stats: {
1601
- totalUsers,
1602
- regularUsers,
1603
- premiumUsers,
1604
- roleDistribution: {
1605
- regular: regularUsers,
1606
- cheap: cheapCount,
1607
- premium: premiumRoleCount,
1608
- vip: vipCount,
1609
- supreme: supremeCount
1610
- },
1611
- database: {
1612
- size: dbSize
1613
- },
1614
- system: {
1615
- ramUsage: ramUsage,
1616
- cpuUsage: cpuPercent,
1617
- storageUsed: storageSize
1618
- }
1619
- }
1620
- });
1621
- } catch (error) {
1622
- console.error('Server stats error:', error);
1623
- res.status(500).json({
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1624
  success: false,
1625
- error: 'Internal server error',
1626
- details: error.message
1627
- });
1628
- }
1629
- });
1630
-
1631
- app.post('/api/admin/set-role', authenticate, async (req, res) => {
1632
- try {
1633
- if (req.user.role !== 'admin') {
1634
- return res.status(403).json({ success: false, error: 'Admin access required' });
1635
- }
1636
-
1637
- const { userId, roleName, customApiKey } = req.body;
1638
-
1639
- if (!userId || !roleName) {
1640
- return res.status(400).json({ success: false, error: 'User ID and role name required' });
1641
- }
1642
-
1643
- const user = await User.findById(userId);
1644
- if (!user) {
1645
- return res.status(404).json({ success: false, error: 'User not found' });
1646
- }
1647
-
1648
- if (user.role === 'admin') {
1649
- return res.status(403).json({ success: false, error: 'Cannot modify admin users' });
1650
- }
1651
-
1652
- const roleConfig = {
1653
- cheap: { limit: 500, premium: true },
1654
- premium: { limit: 1500, premium: true },
1655
- vip: { limit: 2500, premium: true },
1656
- supreme: { limit: 3000, premium: true }
1657
- };
1658
-
1659
- if (!roleConfig[roleName]) {
1660
- return res.status(400).json({ success: false, error: 'Invalid role name' });
1661
- }
1662
-
1663
- const expiresAt = new Date();
1664
- expiresAt.setMonth(expiresAt.getMonth() + 1);
1665
-
1666
- let finalApiKey = user.apikey;
1667
- if (customApiKey && customApiKey.trim()) {
1668
- const existing = await User.findOne({ apikey: customApiKey });
1669
- if (existing && existing._id.toString() !== userId) {
1670
- return res.status(400).json({ success: false, error: 'API key already in use' });
1671
- }
1672
- user.apikey = customApiKey;
1673
- finalApiKey = customApiKey;
1674
- }
1675
-
1676
- user.userRole = roleName;
1677
- user.userRoleExpiresAt = expiresAt;
1678
- user.limit = roleConfig[roleName].limit;
1679
- user.premium = roleConfig[roleName].premium;
1680
- user.premiumExpiredAt = expiresAt;
1681
-
1682
- await user.save();
1683
-
1684
- const userRole = await UserRole.findOne({ userId: user._id });
1685
- if (userRole) {
1686
- userRole.roleName = roleName;
1687
- userRole.customApiKey = customApiKey || null;
1688
- userRole.expiresAt = expiresAt;
1689
- userRole.createdBy = req.user.username;
1690
- await userRole.save();
1691
- } else {
1692
- await UserRole.create({
1693
- userId: user._id,
1694
- roleName,
1695
- customApiKey: customApiKey || null,
1696
- expiresAt,
1697
- createdBy: req.user.username
1698
- });
1699
- }
1700
-
1701
- await logActivity(user._id, user.username, 'role_assigned', `Role ${roleName} assigned by admin`, {
1702
- roleName,
1703
- limit: user.limit,
1704
- expiresAt,
1705
- customApiKey: customApiKey || 'none',
1706
- assignedBy: req.user.username
1707
- });
1708
-
1709
- res.json({
1710
- success: true,
1711
- message: `Role ${roleName} assigned successfully`,
1712
- expiresAt,
1713
- newLimit: user.limit,
1714
- apiKey: user.apikey
1715
- });
1716
- } catch (error) {
1717
- console.error('Set role error:', error);
1718
- res.status(500).json({ success: false, error: 'Internal server error' });
1719
- }
1720
- });
1721
-
1722
- app.get('/api/admin/users', authenticate, async (req, res) => {
1723
- try {
1724
- if (req.user.role !== 'admin') {
1725
- return res.status(403).json({ success: false, error: 'Admin access required' });
1726
- }
1727
-
1728
- const users = await User.find({}, {
1729
- password: 0
1730
- }).sort({ createdAt: -1 });
1731
-
1732
- res.json({
1733
- success: true,
1734
- users: users.map(user => ({
1735
- id: user._id,
1736
- username: user.username,
1737
- email: user.email,
1738
- role: user.role,
1739
- userRole: user.userRole,
1740
- userRoleExpiresAt: user.userRoleExpiresAt,
1741
- premium: user.premium,
1742
- premiumExpiredAt: user.premiumExpiredAt,
1743
- banned: user.banned,
1744
- tempBanned: user.tempBanned,
1745
- tempBanUntil: user.tempBanUntil,
1746
- tempBanReason: user.tempBanReason,
1747
- limit: user.limit,
1748
- requests: user.requests,
1749
- requestsToday: user.requestsToday,
1750
- createdAt: user.createdAt,
1751
- ipAddress: user.ipAddress
1752
- }))
1753
- });
1754
- } catch (error) {
1755
- console.error('Admin users fetch error:', error);
1756
- res.status(500).json({ success: false, error: 'Internal server error' });
1757
- }
1758
- });
1759
-
1760
- app.post('/api/admin/temp-ban', authenticate, async (req, res) => {
1761
- try {
1762
- if (req.user.role !== 'admin') {
1763
- return res.status(403).json({
1764
- success: false, error: 'Admin access required' });
1765
- }
1766
-
1767
- const { userId, banUntil, reason } = req.body;
1768
-
1769
- if (!userId || !banUntil) {
1770
- return res.status(400).json({
1771
- success: false,
1772
- error: 'User ID and ban until date are required'
1773
- });
1774
- }
1775
-
1776
- const user = await User.findById(userId);
1777
- if (!user) {
1778
- return res.status(404).json({ success: false, error: 'User not found' });
1779
- }
1780
-
1781
- if (user.role === 'admin') {
1782
- return res.status(403).json({ success: false, error: 'Cannot ban admin users' });
1783
- }
1784
-
1785
- const banUntilDate = new Date(banUntil);
1786
- if (banUntilDate <= new Date()) {
1787
- return res.status(400).json({
1788
- success: false,
1789
- error: 'Ban until date must be in the future'
1790
- });
1791
- }
1792
-
1793
- user.tempBanned = true;
1794
- user.tempBanUntil = banUntilDate;
1795
- user.tempBanReason = reason || 'No reason provided';
1796
-
1797
- await user.save();
1798
-
1799
- await logActivity(user._id, user.username, 'temp_banned', `User temporarily banned until ${banUntilDate.toLocaleString()}`, {
1800
- bannedBy: req.user.username,
1801
- banUntil: banUntilDate,
1802
- reason: user.tempBanReason
1803
- });
1804
-
1805
- res.json({
1806
- success: true,
1807
- message: `User ${user.username} temporarily banned until ${banUntilDate.toLocaleString()}`
1808
- });
1809
- } catch (error) {
1810
- console.error('Temp ban error:', error);
1811
- res.status(500).json({ success: false, error: 'Internal server error' });
1812
- }
1813
- });
1814
-
1815
- app.post('/api/admin/remove-temp-ban', authenticate, async (req, res) => {
1816
- try {
1817
- if (req.user.role !== 'admin') {
1818
- return res.status(403).json({ success: false, error: 'Admin access required' });
1819
- }
1820
-
1821
- const { userId } = req.body;
1822
-
1823
- if (!userId) {
1824
- return res.status(400).json({
1825
- success: false,
1826
- error: 'User ID is required'
1827
- });
1828
- }
1829
-
1830
- const user = await User.findById(userId);
1831
- if (!user) {
1832
- return res.status(404).json({ success: false, error: 'User not found' });
1833
- }
1834
-
1835
- user.tempBanned = false;
1836
- user.tempBanUntil = null;
1837
- user.tempBanReason = null;
1838
-
1839
- await user.save();
1840
-
1841
- await logActivity(user._id, user.username, 'ban_removed', 'Temporary ban removed by admin', {
1842
- removedBy: req.user.username
1843
- });
1844
-
1845
- res.json({
1846
- success: true,
1847
- message: `Temporary ban removed for user ${user.username}`
1848
- });
1849
- } catch (error) {
1850
- console.error('Remove temp ban error:', error);
1851
- res.status(500).json({ success: false, error: 'Internal server error' });
1852
- }
1853
- });
1854
-
1855
- app.post('/api/admin/redeem-code', authenticate, async (req, res) => {
1856
- try {
1857
- if (req.user.role !== 'admin') {
1858
- return res.status(403).json({ success: false, error: 'Admin access required' });
1859
- }
1860
-
1861
- const { type, limitValue, codeExpired, premiumExpired } = req.body;
1862
-
1863
- if (!type || !codeExpired) {
1864
- return res.status(400).json({
1865
- success: false,
1866
- error: 'Type and code expiration date are required'
1867
- });
1868
- }
1869
-
1870
- const codeExpiredDate = new Date(codeExpired);
1871
- if (codeExpiredDate <= new Date()) {
1872
- return res.status(400).json({
1873
- success: false,
1874
- error: 'Code expiration date must be in the future'
1875
- });
1876
- }
1877
-
1878
- if (type === 'limit' && (!limitValue || limitValue <= 0)) {
1879
- return res.status(400).json({
1880
- success: false,
1881
- error: 'Limit value must be greater than 0 for Limit Only type'
1882
- });
1883
- }
1884
-
1885
- if (type === 'premium' && !premiumExpired) {
1886
- return res.status(400).json({
1887
- success: false,
1888
- error: 'Premium expiration date is required for Premium Only type'
1889
- });
1890
- }
1891
-
1892
- if (type === 'both') {
1893
- if (!limitValue || limitValue <= 0) {
1894
- return res.status(400).json({
1895
- success: false,
1896
- error: 'Limit value must be greater than 0 for Both type'
1897
- });
1898
- }
1899
- if (!premiumExpired) {
1900
- return res.status(400).json({
1901
- success: false,
1902
- error: 'Premium expiration date is required for Both type'
1903
- });
1904
- }
1905
- }
1906
-
1907
- let premiumExpiredDate = null;
1908
- if (premiumExpired) {
1909
- premiumExpiredDate = new Date(premiumExpired);
1910
- if (premiumExpiredDate <= new Date()) {
1911
- return res.status(400).json({
1912
- success: false,
1913
- error: 'Premium expiration date must be in the future'
1914
- });
1915
- }
1916
- }
1917
-
1918
- const code = crypto.randomBytes(4).toString('hex').toUpperCase();
1919
-
1920
- const redeemCode = new RedeemCode({
1921
- code,
1922
- type,
1923
- limitValue: parseInt(limitValue) || 0,
1924
- codeExpired: codeExpiredDate,
1925
- premiumExpired: premiumExpiredDate,
1926
- createdBy: req.user.username
1927
- });
1928
-
1929
- await redeemCode.save();
1930
-
1931
- await logActivity(req.user._id, req.user.username, 'redeem_code_created', `Created redeem code: ${code}`, {
1932
- code,
1933
- type,
1934
- limitValue,
1935
- codeExpired: codeExpiredDate,
1936
- premiumExpired: premiumExpiredDate
1937
- });
1938
-
1939
- res.json({ success: true, code });
1940
- } catch (error) {
1941
- console.error('Redeem code creation error:', error);
1942
- res.status(500).json({ success: false, error: 'Internal server error' });
1943
- }
1944
- });
1945
-
1946
- app.use('/api', checkBanned);
1947
- app.use('/api', apiRateLimit);
1948
-
1949
- let pluginsDir = path.join(__dirname, "plugins");
1950
- let isJavaScriptFile = (fileName) => /\.js$/.test(fileName);
1951
- global.plugins = {};
1952
-
1953
- const loadPlugins = () => {
1954
- if (!fs.existsSync(pluginsDir)) {
1955
- console.log('Plugins directory not found, creating...');
1956
- try {
1957
- fs.mkdirSync(pluginsDir, { recursive: true });
1958
- } catch (error) {
1959
- console.error('Error creating plugins directory:', error);
1960
- }
1961
- return;
1962
- }
1963
-
1964
- for (let pluginFile of fs.readdirSync(pluginsDir).filter(isJavaScriptFile)) {
1965
- try {
1966
- delete require.cache[require.resolve(path.join(pluginsDir, pluginFile))];
1967
- global.plugins[pluginFile] = require(path.join(pluginsDir, pluginFile));
1968
- } catch (error) {
1969
- console.error(`Error loading plugin ${pluginFile}:`, error.message);
1970
- delete global.plugins[pluginFile];
1971
- }
1972
- }
1973
-
1974
- console.log('Loaded plugins:', Object.keys(global.plugins));
1975
- };
1976
-
1977
- global.reload = (event, filename) => {
1978
- if (/\.js$/.test(filename)) {
1979
- let fullFilePath = path.join(pluginsDir, filename);
1980
- if (fullFilePath in require.cache) {
1981
- delete require.cache[fullFilePath];
1982
- if (fs.existsSync(fullFilePath)) {
1983
- console.log(`♻️ Re-requiring plugin '${filename}'`);
1984
- } else {
1985
- console.log(`🗑️ Deleted plugin '${filename}'`);
1986
- return delete global.plugins[filename];
1987
- }
1988
- } else {
1989
- console.log(`🔁 Requiring new plugin '${filename}'`);
1990
- }
1991
-
1992
- let errorCheck = syntaxError(fs.readFileSync(fullFilePath), filename);
1993
- if (errorCheck) {
1994
- console.error(`❌ Syntax error while loading '${filename}':\n${errorCheck}`);
1995
- } else {
1996
- try {
1997
- global.plugins[filename] = require(fullFilePath);
1998
- reloadHandler();
1999
- } catch (error) {
2000
- console.error(`Error loading plugin ${filename}:`, error);
2001
- } finally {
2002
- global.plugins = Object.fromEntries(Object.entries(global.plugins).sort(([a], [b]) => a.localeCompare(b)));
2003
- }
2004
- }
2005
- }
2006
- };
2007
-
2008
- const reloadHandler = () => {
2009
- const routes = [];
2010
-
2011
- Object.keys(global.plugins).forEach(file => {
2012
- const plugin = global.plugins[file];
2013
- if (plugin && plugin.enabled && plugin.routes && plugin.handler) {
2014
- plugin.routes.forEach(route => {
2015
- routes.push({ route, plugin, file });
2016
- });
2017
- }
2018
- });
2019
-
2020
- routes.forEach(({ route, plugin, file }) => {
2021
- const method = (plugin.type || 'get').toLowerCase();
2022
- if (app[method] && typeof app[method] === 'function') {
2023
- app[method](`/${route}`, (req, res, next) => {
2024
- req.limitDeduction = plugin.limit || 1;
2025
- next();
2026
- }, validateApiKey, async (req, res) => {
2027
- const startTime = Date.now();
2028
- try {
2029
- await plugin.handler(req, res);
2030
-
2031
- await RequestLog.create({
2032
- userId: req.apiUser._id,
2033
- username: req.apiUser.username,
2034
- apikey: req.apiUser.apikey,
2035
- endpoint: route,
2036
- ipAddress: req.realIP,
2037
- userAgent: req.get('User-Agent'),
2038
- success: true,
2039
- responseTime: Date.now() - startTime,
2040
- limitDeducted: req.limitDeducted || 1
2041
- });
2042
- } catch (error) {
2043
- console.error(`Plugin ${plugin.name} error:`, error);
2044
-
2045
- await RequestLog.create({
2046
- userId: req.apiUser._id,
2047
- username: req.apiUser.username,
2048
- apikey: req.apiUser.apikey,
2049
- endpoint: route,
2050
- ipAddress: req.realIP,
2051
- userAgent: req.get('User-Agent'),
2052
- success: false,
2053
- responseTime: Date.now() - startTime,
2054
- limitDeducted: req.limitDeducted || 1
2055
- });
2056
-
2057
- if (!res.headersSent) {
2058
- res.status(500).json({
2059
- success: false,
2060
- error: 'Plugin execution failed'
2061
- });
2062
- }
2063
- }
2064
- });
2065
- console.log(`✅ Registered route: ${method.toUpperCase()} /${route} from ${file}`);
2066
- }
2067
- });
2068
- };
2069
-
2070
- Object.freeze(global.reload);
2071
- fs.watch(pluginsDir, global.reload);
2072
-
2073
- setInterval(async () => {
2074
- const now = new Date();
2075
-
2076
- if (now.getHours() === 0 && now.getMinutes() === 0) {
2077
- console.log('Running daily limit reset at midnight...');
2078
-
2079
- try {
2080
- const users = await User.find({});
2081
-
2082
- for (const user of users) {
2083
- await resetUserLimitIfNeeded(user);
2084
- }
2085
-
2086
- console.log('Daily limit reset completed for all users');
2087
- } catch (error) {
2088
- console.error('Daily reset error:', error);
2089
- }
2090
- }
2091
- }, 60000);
2092
-
2093
- initializeAdmin();
2094
- loadPlugins();
2095
- reloadHandler();
2096
-
2097
- app.use((err, req, res, next) => {
2098
- console.error('Unhandled error:', err);
2099
- res.status(500).json({
2100
- success: false,
2101
- error: 'Internal server error'
2102
- });
2103
- });
2104
-
2105
- const PORT = process.env.PORT || 7860;
2106
- app.listen(PORT, () => {
2107
- console.log(`DashX API Server running on port ${PORT}`);
2108
- console.log('=== ADMIN ACCOUNT INFO ===');
2109
- console.log('Username: HERXA');
2110
- console.log('Password: BTXHZ');
2111
- console.log('API Key: DHX-M3SA');
2112
- console.log('Limit: 9999');
2113
- console.log('=========================');
2114
- console.log('Database connected successfully');
2115
- console.log('Plugin auto-reload enabled');
2116
- console.log('Daily reset cron job started');
2117
- });
 
793
  </div>
794
  </div>
795
  <div style="background: #f8f9fa; padding: 25px 30px; text-align: center; border-top: 1px solid #e9ecef;">
796
+ <p style="color: #6c757d; margin: 0 0 10px 0; font-size: 14px;">
 
797
  Need help? Contact our support team
798
  </p>
799
  <p style="color: #adb5bd; margin: 0; font-size: 12px;">
800
  © 2025 DashX. All rights reserved.
801
  </p>
802
+ </div>
803
+ </div>
804
+ </div>
805
+ </body>
806
+ </html>
807
+ `;
808
+
809
+ await transporter.sendMail({
810
+ from: 'dashxapi@gmail.com',
811
+ to: email,
812
+ subject: 'DashX - Email Verification',
813
+ html: emailTemplate
814
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
815
 
816
+ res.json({
817
+ success: true,
818
+ message: 'Verification code sent to your email. Please verify within 15 minutes.',
819
+ expiresIn: '15 minutes'
820
+ });
821
 
822
+ } catch (error) {
823
+ console.error('Registration error:', error);
824
+ res.status(500).json({ success: false, error: 'Internal server error' });
825
+ }
826
+ });
 
827
 
828
+ app.post('/api/auth/verify', checkBanned, authRateLimit, async (req, res) => {
829
+ try {
830
+ const { email, code } = req.body;
831
 
832
+ if (!email || !code) {
833
+ return res.status(400).json({
834
+ success: false,
835
+ error: 'Email and verification code are required'
836
+ });
837
+ }
838
+
839
+ const pendingVerification = await PendingVerification.findOne({
840
+ email,
841
+ verificationCode: code
842
+ });
843
+
844
+ if (!pendingVerification) {
845
+ return res.status(400).json({
846
+ success: false,
847
+ error: 'Invalid verification code or code has expired'
848
+ });
849
+ }
850
+
851
+ const existingUser = await User.findOne({
852
+ $or: [{ email: pendingVerification.email }, { username: pendingVerification.username }]
853
+ });
854
+
855
+ if (existingUser) {
856
+ await PendingVerification.deleteOne({ _id: pendingVerification._id });
857
+ return res.status(400).json({
858
+ success: false,
859
+ error: 'User already exists in database'
860
+ });
861
+ }
862
+
863
+ const apikey = generateApiKey();
864
+
865
+ const user = new User({
866
+ username: pendingVerification.username,
867
+ email: pendingVerification.email,
868
+ password: pendingVerification.password,
869
+ apikey: apikey,
870
+ profileUrl: 'https://files.catbox.moe/8l6hhm',
871
+ verified: true,
872
+ ipAddress: pendingVerification.ipAddress,
873
+ role: 'user',
874
+ premium: false,
875
+ limit: 30,
876
+ requests: 0,
877
+ requestsToday: 0,
878
+ lastReset: new Date(),
879
+ banned: false
880
+ });
881
+
882
+ await user.save();
883
+ await PendingVerification.deleteOne({ _id: pendingVerification._id });
884
+
885
+ await logActivity(user._id, user.username, 'api_key_generated', 'Account created and verified successfully', {
886
+ apikey: user.apikey,
887
+ registrationIP: pendingVerification.ipAddress
888
+ });
889
+
890
+ const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '30d' });
891
+
892
+ res.json({
893
+ success: true,
894
+ token,
895
+ user: {
896
+ id: user._id,
897
+ username: user.username,
898
+ email: user.email,
899
+ apikey: user.apikey,
900
+ profileUrl: user.profileUrl,
901
+ premium: user.premium,
902
+ limit: user.limit
903
+ },
904
+ message: 'Account created and verified successfully!'
905
+ });
906
+
907
+ } catch (error) {
908
+ console.error('Verification error:', error);
909
+ res.status(500).json({ success: false, error: 'Internal server error' });
910
+ }
911
+ });
912
+
913
+ app.get('/api/admin/search-users', authenticate, async (req, res) => {
914
+ try {
915
+ if (req.user.role !== 'admin') {
916
+ return res.status(403).json({ success: false, error: 'Admin access required' });
917
+ }
918
+
919
+ const { query } = req.query;
920
+ if (!query) {
921
+ return res.json({ success: true, users: [] });
922
+ }
923
+
924
+ const users = await User.find({
925
+ $or: [
926
+ { username: { $regex: query, $options: 'i' } },
927
+ { email: { $regex: query, $options: 'i' } }
928
+ ],
929
+ role: { $ne: 'admin' }
930
+ }).limit(10).select('username email limit premium role');
931
+
932
+ res.json({ success: true, users });
933
+ } catch (error) {
934
+ console.error('Search users error:', error);
935
+ res.status(500).json({ success: false, error: 'Internal server error' });
936
+ }
937
+ });
938
+
939
+ app.get('/api/admin/user-role/:userId', authenticate, async (req, res) => {
940
+ try {
941
+ if (req.user.role !== 'admin') {
942
+ return res.status(403).json({ success: false, error: 'Admin access required' });
943
+ }
944
+
945
+ const userRole = await UserRole.findOne({ userId: req.params.userId });
946
+ res.json({ success: true, role: userRole });
947
+ } catch (error) {
948
+ res.status(500).json({ success: false, error: 'Internal server error' });
949
+ }
950
+ });
951
+
952
+ app.post('/api/auth/login', checkBanned, authRateLimit, async (req, res) => {
953
+ try {
954
+ const { email, password } = req.body;
955
+
956
+ if (!email || !password) {
957
+ return res.status(400).json({
958
+ success: false,
959
+ error: 'Email and password are required'
960
+ });
961
+ }
962
+
963
+ const user = await User.findOne({ email });
964
+ if (!user) {
965
+ return res.status(400).json({ success: false, error: 'Invalid credentials' });
966
+ }
967
+
968
+ const isValidPassword = await bcrypt.compare(password, user.password);
969
+ if (!isValidPassword) {
970
+ return res.status(400).json({ success: false, error: 'Invalid credentials' });
971
+ }
972
+
973
+ if (user.banned) {
974
+ return res.status(403).json({ success: false, error: 'Account is permanently banned' });
975
+ }
976
+
977
+ await checkPremiumExpiry(user);
978
+ await checkRoleExpiry(user);
979
+ await resetUserLimitIfNeeded(user);
980
+
981
+ const isTempBanned = await checkTempBan(user);
982
+ if (isTempBanned) {
983
+ const banUntil = new Date(user.tempBanUntil);
984
+ return res.status(403).json({
985
+ success: false,
986
+ error: `Account temporarily banned until ${banUntil.toLocaleString()}. Reason: ${user.tempBanReason || 'No reason provided'}`
987
+ });
988
+ }
989
+
990
+ const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '30d' });
991
+
992
+ res.json({
993
+ success: true,
994
+ token,
995
+ user: {
996
+ id: user._id,
997
+ username: user.username,
998
+ email: user.email,
999
+ apikey: user.apikey,
1000
+ profileUrl: user.profileUrl,
1001
+ premium: user.premium,
1002
+ premiumExpiredAt: user.premiumExpiredAt,
1003
+ limit: user.limit,
1004
+ role: user.role
1005
+ }
1006
+ });
1007
+ } catch (error) {
1008
+ console.error('Login error:', error);
1009
+ res.status(500).json({ success: false, error: 'Internal server error' });
1010
+ }
1011
+ });
1012
+
1013
+ app.post('/api/auth/admin-login', checkBanned, authRateLimit, async (req, res) => {
1014
+ try {
1015
+ const { username, password } = req.body;
1016
+
1017
+ if (username === 'HERXA' && password === 'BTXHZ') {
1018
+ let admin = await User.findOne({ username: 'HERXA' });
1019
+ if (!admin) {
1020
+ admin = new User({
1021
+ username: 'HERXA',
1022
+ email: 'admin@dashx.com',
1023
+ password: await bcrypt.hash('BTXHZ', 12),
1024
+ apikey: 'DHX-M3SA',
1025
+ profileUrl: 'https://files.catbox.moe/8l6hhm',
1026
+ verified: true,
1027
+ role: 'admin',
1028
+ premium: true,
1029
+ limit: 9999,
1030
+ ipAddress: req.realIP
1031
+ });
1032
+ await admin.save();
1033
+ } else {
1034
+ admin.apikey = 'DHX-M3SA';
1035
+ admin.limit = 9999;
1036
+ admin.role = 'admin';
1037
+ admin.premium = true;
1038
+ await admin.save();
1039
+ }
1040
+
1041
+ const token = jwt.sign({ userId: admin._id }, JWT_SECRET, { expiresIn: '30d' });
1042
+ return res.json({
1043
+ success: true,
1044
+ token,
1045
+ user: {
1046
+ id: admin._id,
1047
+ username: admin.username,
1048
+ role: admin.role,
1049
+ apikey: admin.apikey,
1050
+ profileUrl: admin.profileUrl,
1051
+ limit: admin.limit
1052
+ }
1053
+ });
1054
+ }
1055
+
1056
+ const admin = await User.findOne({ username, role: 'admin' });
1057
+ if (!admin || !await bcrypt.compare(password, admin.password)) {
1058
+ return res.status(400).json({ success: false, error: 'Invalid admin credentials' });
1059
+ }
1060
+
1061
+ const token = jwt.sign({ userId: admin._id }, JWT_SECRET, { expiresIn: '30d' });
1062
+ res.json({
1063
+ success: true,
1064
+ token,
1065
+ user: {
1066
+ id: admin._id,
1067
+ username: admin.username,
1068
+ role: admin.role,
1069
+ apikey: admin.apikey,
1070
+ profileUrl: admin.profileUrl,
1071
+ limit: admin.limit
1072
+ }
1073
+ });
1074
+ } catch (error) {
1075
+ console.error('Admin login error:', error);
1076
+ res.status(500).json({ success: false, error: 'Internal server error' });
1077
+ }
1078
+ });
1079
 
1080
  app.get('/api/user/profile', authenticate, async (req, res) => {
1081
  try {
 
1135
  }
1136
  });
1137
 
1138
+ app.get('/api/user/activities', authenticate, async (req, res) => {
1139
+ try {
1140
+ const activities = await Activity.find({ userId: req.user._id })
1141
+ .sort({ timestamp: -1 })
1142
+ .limit(50);
1143
+
1144
+ const requestLogs = await RequestLog.find({ userId: req.user._id })
1145
+ .sort({ timestamp: -1 })
1146
+ .limit(20);
1147
+
1148
+ res.json({
1149
+ success: true,
1150
+ activities: activities.map(activity => ({
1151
+ type: activity.type,
1152
+ description: activity.description,
1153
+ timestamp: activity.timestamp,
1154
+ timeAgo: getTimeAgo(activity.timestamp),
1155
+ metadata: activity.metadata
1156
+ })),
1157
+ requestLogs: requestLogs.map(log => ({
1158
+ endpoint: log.endpoint,
1159
+ timestamp: log.timestamp,
1160
+ timeAgo: getTimeAgo(log.timestamp),
1161
+ success: log.success,
1162
+ ipAddress: log.ipAddress,
1163
+ limitDeducted: log.limitDeducted
1164
+ }))
1165
+ });
1166
+ } catch (error) {
1167
+ console.error('Activities fetch error:', error);
1168
+ res.status(500).json({ success: false, error: 'Internal server error' });
1169
+ }
1170
+ });
1171
+
1172
+ app.get('/api/user/usage-stats', authenticate, async (req, res) => {
1173
  try {
1174
  const userId = req.user._id.toString();
1175
 
 
1176
  const todayStart = new Date();
1177
  todayStart.setHours(0, 0, 0, 0);
1178
 
 
1181
  timestamp: { $gte: todayStart }
1182
  });
1183
 
 
1184
  const userTotalRequests = await RequestLog.countDocuments({
1185
  userId
1186
  });
 
1244
  }
1245
  });
1246
 
1247
+ app.put('/api/user/profile', authenticate, async (req, res) => {
1248
+ try {
1249
+ const { username, profileUrl, customApiKey } = req.body;
1250
+ let updated = false;
1251
+
1252
+ if (username && username !== req.user.username) {
1253
+ const existing = await User.findOne({ username });
1254
+ if (existing) {
1255
+ return res.status(400).json({ success: false, error: 'Username already taken' });
1256
+ }
1257
+
1258
+ const oldUsername = req.user.username;
1259
+ req.user.username = username;
1260
+ updated = true;
1261
+
1262
+ await logActivity(req.user._id, req.user.username, 'profile_updated', `Username changed from ${oldUsername} to ${username}`, {
1263
+ oldUsername,
1264
+ newUsername: username
1265
+ });
1266
+ }
1267
+
1268
+ if (profileUrl !== undefined && profileUrl !== req.user.profileUrl) {
1269
+ req.user.profileUrl = profileUrl;
1270
+ updated = true;
1271
+
1272
+ await logActivity(req.user._id, req.user.username, 'profile_updated', 'Profile URL updated', {
1273
+ newProfileUrl: profileUrl
1274
+ });
1275
+ }
1276
+
1277
+ if (customApiKey && (req.user.premium || req.user.role === 'admin')) {
1278
+ const existing = await User.findOne({ apikey: customApiKey });
1279
+ if (existing && existing._id.toString() !== req.user._id.toString()) {
1280
+ return res.status(400).json({ success: false, error: 'API key already in use' });
1281
+ }
1282
+
1283
+ const oldApiKey = req.user.apikey;
1284
+ req.user.apikey = customApiKey;
1285
+ updated = true;
1286
+
1287
+ await logActivity(req.user._id, req.user.username, 'api_key_updated', 'Custom API key set', {
1288
+ oldApiKey,
1289
+ newApiKey: customApiKey
1290
+ });
1291
+ }
1292
+
1293
+ if (updated) {
1294
+ await req.user.save();
1295
+ }
1296
+
1297
+ res.json({ success: true, message: 'Profile updated successfully' });
1298
+ } catch (error) {
1299
+ console.error('Profile update error:', error);
1300
+ res.status(500).json({ success: false, error: 'Internal server error' });
1301
+ }
1302
+ });
1303
+
1304
+ app.delete('/api/user/account', authenticate, async (req, res) => {
1305
+ try {
1306
+ if (req.user.role === 'admin') {
1307
+ return res.status(403).json({ success: false, error: 'Cannot delete admin account' });
1308
+ }
1309
+
1310
+ await User.deleteOne({ _id: req.user._id });
1311
+ await Activity.deleteMany({ userId: req.user._id });
1312
+ res.json({ success: true, message: 'Account deleted successfully' });
1313
+ } catch (error) {
1314
+ console.error('Account deletion error:', error);
1315
+ res.status(500).json({ success: false, error: 'Internal server error' });
1316
+ }
1317
+ });
1318
+
1319
+ app.get('/api/stats/all', async (req, res) => {
1320
  try {
1321
  const totalUsers = await User.countDocuments();
1322
  const totalRequests = await RequestLog.countDocuments();
 
1423
  }
1424
  });
1425
 
1426
+ app.post('/api/user/regenerate-key', authenticate, async (req, res) => {
1427
+ try {
1428
+ if (!req.user.premium && req.user.role !== 'admin') {
1429
+ return res.status(403).json({ success: false, error: 'Premium feature only' });
1430
+ }
1431
+
1432
+ const oldApikey = req.user.apikey;
1433
+
1434
+ if (req.user.role === 'admin') {
1435
+ req.user.apikey = 'DHX-M3SA';
1436
+ } else {
1437
+ req.user.apikey = generateApiKey();
1438
+ }
1439
+
1440
+ await req.user.save();
1441
+
1442
+ await logActivity(req.user._id, req.user.username, 'api_key_generated', 'API key regenerated', {
1443
+ oldApikey,
1444
+ newApikey: req.user.apikey
1445
+ });
1446
+
1447
+ res.json({ success: true, apikey: req.user.apikey });
1448
+ } catch (error) {
1449
+ console.error('API key regeneration error:', error);
1450
+ res.status(500).json({ success: false, error: 'Internal server error' });
1451
+ }
1452
+ });
1453
+
1454
+ app.post('/api/user/redeem', authenticate, async (req, res) => {
1455
+ try {
1456
+ const { code } = req.body;
1457
 
1458
+ if (!code) {
1459
+ return res.status(400).json({
1460
+ success: false,
1461
+ error: 'Redeem code is required'
1462
+ });
1463
+ }
1464
 
1465
+ const redeemCode = await RedeemCode.findOne({ code });
 
 
 
 
1466
 
1467
+ if (!redeemCode) {
1468
+ return res.status(400).json({
1469
+ success: false,
1470
+ error: 'This redeem code is not available anymore or never exist'
1471
+ });
1472
+ }
1473
 
1474
+ if (redeemCode.used) {
1475
+ return res.status(400).json({
1476
+ success: false,
1477
+ error: 'This redeem code has already been used'
1478
+ });
1479
+ }
1480
 
1481
+ if (new Date() > redeemCode.codeExpired) {
1482
+ return res.status(400).json({
1483
+ success: false,
1484
+ error: 'This redeem code is not available anymore or never exist'
1485
+ });
1486
+ }
1487
 
1488
+ let benefits = [];
 
 
1489
 
1490
+ if (redeemCode.type === 'limit' || redeemCode.type === 'both') {
1491
+ req.user.limit += redeemCode.limitValue;
1492
+ benefits.push(`+${redeemCode.limitValue} API requests`);
1493
+ }
 
 
1494
 
1495
+ if (redeemCode.type === 'premium' || redeemCode.type === 'both') {
1496
+ req.user.premium = true;
1497
+ req.user.premiumExpiredAt = redeemCode.premiumExpired;
1498
+ benefits.push(`Premium activated until ${redeemCode.premiumExpired.toLocaleString()}`);
1499
+ }
1500
 
1501
+ if (redeemCode.type === 'premium' && redeemCode.limitValue > 0) {
1502
+ req.user.limit += redeemCode.limitValue;
1503
+ benefits.push(`+${redeemCode.limitValue} API requests (bonus)`);
1504
+ }
 
 
1505
 
1506
+ redeemCode.used = true;
1507
+ redeemCode.usedBy = req.user.username;
 
 
 
 
1508
 
1509
+ await req.user.save();
1510
+ await redeemCode.save();
1511
+
1512
+ await logActivity(req.user._id, req.user.username, 'redeem_code_used', `Redeem code used: ${benefits.join(', ')}`, {
1513
+ code: code,
1514
+ type: redeemCode.type,
1515
+ benefits
1516
+ });
1517
+
1518
+ res.json({
1519
+ success: true,
1520
+ message: 'Redeem code used successfully',
1521
+ benefits
1522
+ });
1523
+ } catch (error) {
1524
+ console.error('Redeem code error:', error);
1525
+ res.status(500).json({ success: false, error: 'Internal server error' });
1526
+ }
1527
+ });
1528
+
1529
+ app.get('/api/admin/stats', authenticate, async (req, res) => {
1530
+ try {
1531
+ if (req.user.role !== 'admin') {
1532
+ return res.status(403).json({ success: false, error: 'Admin access required' });
1533
+ }
1534
+
1535
+ const totalUsers = await User.countDocuments();
1536
+ const pendingUsers = await PendingVerification.countDocuments();
1537
+ const totalRequests = await RequestLog.countDocuments();
1538
+
1539
+ const todayStart = new Date();
1540
+ todayStart.setHours(0, 0, 0, 0);
1541
+
1542
+ const todayRequests = await RequestLog.countDocuments({
1543
+ timestamp: { $gte: todayStart }
1544
+ });
1545
+
1546
+ res.json({
1547
+ success: true,
1548
+ stats: {
1549
+ totalUsers,
1550
+ pendingUsers,
1551
+ totalRequests,
1552
+ todayRequests
1553
+ }
1554
+ });
1555
+ } catch (error) {
1556
+ console.error('Admin stats error:', error);
1557
+ res.status(500).json({ success: false, error: 'Internal server error' });
1558
+ }
1559
+ });
1560
+
1561
+ app.get('/api/server-stats', async (req, res) => {
1562
+ try {
1563
+ const totalUsers = await User.countDocuments();
1564
+ const regularUsers = await User.countDocuments({
1565
+ $and: [
1566
+ { premium: false },
1567
+ { $or: [{ userRole: null }, { userRole: { $exists: false } }] }
1568
+ ]
1569
+ });
1570
+ const premiumUsers = await User.countDocuments({ premium: true });
1571
+
1572
+ const cheapCount = await User.countDocuments({ userRole: 'cheap' });
1573
+ const premiumRoleCount = await User.countDocuments({ userRole: 'premium' });
1574
+ const vipCount = await User.countDocuments({ userRole: 'vip' });
1575
+ const supremeCount = await User.countDocuments({ userRole: 'supreme' });
1576
+
1577
+ let dbSize = '0 MB';
1578
+ let storageSize = '0 GB';
1579
+
1580
+ try {
1581
+ const dbStats = await mongoose.connection.db.stats();
1582
+ dbSize = (dbStats.dataSize / 1024 / 1024).toFixed(2) + ' MB';
1583
+ storageSize = (dbStats.storageSize / 1024 / 1024 / 1024).toFixed(2) + ' GB';
1584
+ } catch (dbError) {
1585
+ console.log('DB stats not available:', dbError.message);
1586
+ }
1587
+
1588
+ const memUsage = process.memoryUsage();
1589
+ const ramUsage = (memUsage.heapUsed / 1024 / 1024).toFixed(2) + ' MB';
1590
+
1591
+ const cpuUsage = process.cpuUsage();
1592
+ const cpuPercent = ((cpuUsage.user + cpuUsage.system) / 1000000).toFixed(2);
1593
+
1594
+ res.json({
1595
+ success: true,
1596
+ stats: {
1597
+ totalUsers,
1598
+ regularUsers,
1599
+ premiumUsers,
1600
+ roleDistribution: {
1601
+ regular: regularUsers,
1602
+ cheap: cheapCount,
1603
+ premium: premiumRoleCount,
1604
+ vip: vipCount,
1605
+ supreme: supremeCount
1606
+ },
1607
+ database: {
1608
+ size: dbSize
1609
+ },
1610
+ system: {
1611
+ ramUsage: ramUsage,
1612
+ cpuUsage: cpuPercent,
1613
+ storageUsed: storageSize
1614
+ }
1615
+ }
1616
+ });
1617
+ } catch (error) {
1618
+ console.error('Server stats error:', error);
1619
+ res.status(500).json({
1620
+ success: false,
1621
+ error: 'Internal server error',
1622
+ details: error.message
1623
+ });
1624
+ }
1625
+ });
1626
+
1627
+ app.post('/api/admin/set-role', authenticate, async (req, res) => {
1628
+ try {
1629
+ if (req.user.role !== 'admin') {
1630
+ return res.status(403).json({ success: false, error: 'Admin access required' });
1631
+ }
1632
+
1633
+ const { userId, roleName, customApiKey } = req.body;
1634
+
1635
+ if (!userId || !roleName) {
1636
+ return res.status(400).json({ success: false, error: 'User ID and role name required' });
1637
+ }
1638
+
1639
+ const user = await User.findById(userId);
1640
+ if (!user) {
1641
+ return res.status(404).json({ success: false, error: 'User not found' });
1642
+ }
1643
+
1644
+ if (user.role === 'admin') {
1645
+ return res.status(403).json({ success: false, error: 'Cannot modify admin users' });
1646
+ }
1647
+
1648
+ const roleConfig = {
1649
+ cheap: { limit: 500, premium: true },
1650
+ premium: { limit: 1500, premium: true },
1651
+ vip: { limit: 2500, premium: true },
1652
+ supreme: { limit: 3000, premium: true }
1653
+ };
1654
+
1655
+ if (!roleConfig[roleName]) {
1656
+ return res.status(400).json({ success: false, error: 'Invalid role name' });
1657
+ }
1658
+
1659
+ const expiresAt = new Date();
1660
+ expiresAt.setMonth(expiresAt.getMonth() + 1);
1661
+
1662
+ let finalApiKey = user.apikey;
1663
+ if (customApiKey && customApiKey.trim()) {
1664
+ const existing = await User.findOne({ apikey: customApiKey });
1665
+ if (existing && existing._id.toString() !== userId) {
1666
+ return res.status(400).json({ success: false, error: 'API key already in use' });
1667
+ }
1668
+ user.apikey = customApiKey;
1669
+ finalApiKey = customApiKey;
1670
+ }
1671
+
1672
+ user.userRole = roleName;
1673
+ user.userRoleExpiresAt = expiresAt;
1674
+ user.limit = roleConfig[roleName].limit;
1675
+ user.premium = roleConfig[roleName].premium;
1676
+ user.premiumExpiredAt = expiresAt;
1677
+
1678
+ await user.save();
1679
+
1680
+ const userRole = await UserRole.findOne({ userId: user._id });
1681
+ if (userRole) {
1682
+ userRole.roleName = roleName;
1683
+ userRole.customApiKey = customApiKey || null;
1684
+ userRole.expiresAt = expiresAt;
1685
+ userRole.createdBy = req.user.username;
1686
+ await userRole.save();
1687
+ } else {
1688
+ await UserRole.create({
1689
+ userId: user._id,
1690
+ roleName,
1691
+ customApiKey: customApiKey || null,
1692
+ expiresAt,
1693
+ createdBy: req.user.username
1694
+ });
1695
+ }
1696
+
1697
+ await logActivity(user._id, user.username, 'role_assigned', `Role ${roleName} assigned by admin`, {
1698
+ roleName,
1699
+ limit: user.limit,
1700
+ expiresAt,
1701
+ customApiKey: customApiKey || 'none',
1702
+ assignedBy: req.user.username
1703
+ });
1704
+
1705
+ res.json({
1706
+ success: true,
1707
+ message: `Role ${roleName} assigned successfully`,
1708
+ expiresAt,
1709
+ newLimit: user.limit,
1710
+ apiKey: user.apikey
1711
+ });
1712
+ } catch (error) {
1713
+ console.error('Set role error:', error);
1714
+ res.status(500).json({ success: false, error: 'Internal server error' });
1715
+ }
1716
+ });
1717
+
1718
+ app.get('/api/admin/users', authenticate, async (req, res) => {
1719
+ try {
1720
+ if (req.user.role !== 'admin') {
1721
+ return res.status(403).json({ success: false, error: 'Admin access required' });
1722
+ }
1723
+
1724
+ const users = await User.find({}, {
1725
+ password: 0
1726
+ }).sort({ createdAt: -1 });
1727
+
1728
+ res.json({
1729
+ success: true,
1730
+ users: users.map(user => ({
1731
+ id: user._id,
1732
+ username: user.username,
1733
+ email: user.email,
1734
+ role: user.role,
1735
+ userRole: user.userRole,
1736
+ userRoleExpiresAt: user.userRoleExpiresAt,
1737
+ premium: user.premium,
1738
+ premiumExpiredAt: user.premiumExpiredAt,
1739
+ banned: user.banned,
1740
+ tempBanned: user.tempBanned,
1741
+ tempBanUntil: user.tempBanUntil,
1742
+ tempBanReason: user.tempBanReason,
1743
+ limit: user.limit,
1744
+ requests: user.requests,
1745
+ requestsToday: user.requestsToday,
1746
+ createdAt: user.createdAt,
1747
+ ipAddress: user.ipAddress
1748
+ }))
1749
+ });
1750
+ } catch (error) {
1751
+ console.error('Admin users fetch error:', error);
1752
+ res.status(500).json({ success: false, error: 'Internal server error' });
1753
+ }
1754
+ });
1755
+
1756
+ app.post('/api/admin/temp-ban', authenticate, async (req, res) => {
1757
+ try {
1758
+ if (req.user.role !== 'admin') {
1759
+ return res.status(403).json({ success: false, error: 'Admin access required' });
1760
+ }
1761
+
1762
+ const { userId, banUntil, reason } = req.body;
1763
+
1764
+ if (!userId || !banUntil) {
1765
+ return res.status(400).json({
1766
+ success: false,
1767
+ error: 'User ID and ban until date are required'
1768
+ });
1769
+ }
1770
+
1771
+ const user = await User.findById(userId);
1772
+ if (!user) {
1773
+ return res.status(404).json({ success: false, error: 'User not found' });
1774
+ }
1775
+
1776
+ if (user.role === 'admin') {
1777
+ return res.status(403).json({ success: false, error: 'Cannot ban admin users' });
1778
+ }
1779
+
1780
+ const banUntilDate = new Date(banUntil);
1781
+ if (banUntilDate <= new Date()) {
1782
+ return res.status(400).json({
1783
+ success: false,
1784
+ error: 'Ban until date must be in the future'
1785
+ });
1786
+ }
1787
+
1788
+ user.tempBanned = true;
1789
+ user.tempBanUntil = banUntilDate;
1790
+ user.tempBanReason = reason || 'No reason provided';
1791
+
1792
+ await user.save();
1793
+
1794
+ await logActivity(user._id, user.username, 'temp_banned', `User temporarily banned until ${banUntilDate.toLocaleString()}`, {
1795
+ bannedBy: req.user.username,
1796
+ banUntil: banUntilDate,
1797
+ reason: user.tempBanReason
1798
+ });
1799
+
1800
+ res.json({
1801
+ success: true,
1802
+ message: `User ${user.username} temporarily banned until ${banUntilDate.toLocaleString()}`
1803
+ });
1804
+ } catch (error) {
1805
+ console.error('Temp ban error:', error);
1806
+ res.status(500).json({ success: false, error: 'Internal server error' });
1807
+ }
1808
+ });
1809
+
1810
+ app.post('/api/admin/remove-temp-ban', authenticate, async (req, res) => {
1811
+ try {
1812
+ if (req.user.role !== 'admin') {
1813
+ return res.status(403).json({ success: false, error: 'Admin access required' });
1814
+ }
1815
+
1816
+ const { userId } = req.body;
1817
+
1818
+ if (!userId) {
1819
+ return res.status(400).json({
1820
+ success: false,
1821
+ error: 'User ID is required'
1822
+ });
1823
+ }
1824
+
1825
+ const user = await User.findById(userId);
1826
+ if (!user) {
1827
+ return res.status(404).json({ success: false, error: 'User not found' });
1828
+ }
1829
+
1830
+ user.tempBanned = false;
1831
+ user.tempBanUntil = null;
1832
+ user.tempBanReason = null;
1833
+
1834
+ await user.save();
1835
+
1836
+ await logActivity(user._id, user.username, 'ban_removed', 'Temporary ban removed by admin', {
1837
+ removedBy: req.user.username
1838
+ });
1839
+
1840
+ res.json({
1841
+ success: true,
1842
+ message: `Temporary ban removed for user ${user.username}`
1843
+ });
1844
+ } catch (error) {
1845
+ console.error('Remove temp ban error:', error);
1846
+ res.status(500).json({ success: false, error: 'Internal server error' });
1847
+ }
1848
+ });
1849
+
1850
+ app.post('/api/admin/redeem-code', authenticate, async (req, res) => {
1851
+ try {
1852
+ if (req.user.role !== 'admin') {
1853
+ return res.status(403).json({ success: false, error: 'Admin access required' });
1854
+ }
1855
+
1856
+ const { type, limitValue, codeExpired, premiumExpired } = req.body;
1857
+
1858
+ if (!type || !codeExpired) {
1859
+ return res.status(400).json({
1860
+ success: false,
1861
+ error: 'Type and code expiration date are required'
1862
+ });
1863
+ }
1864
+
1865
+ const codeExpiredDate = new Date(codeExpired);
1866
+ if (codeExpiredDate <= new Date()) {
1867
+ return res.status(400).json({
1868
+ success: false,
1869
+ error: 'Code expiration date must be in the future'
1870
+ });
1871
+ }
1872
+
1873
+ if (type === 'limit' && (!limitValue || limitValue <= 0)) {
1874
+ return res.status(400).json({
1875
+ success: false,
1876
+ error: 'Limit value must be greater than 0 for Limit Only type'
1877
+ });
1878
+ }
1879
+
1880
+ if (type === 'premium' && !premiumExpired) {
1881
+ return res.status(400).json({
1882
+ success: false,
1883
+ error: 'Premium expiration date is required for Premium Only type'
1884
+ });
1885
+ }
1886
+
1887
+ if (type === 'both') {
1888
+ if (!limitValue || limitValue <= 0) {
1889
+ return res.status(400).json({
1890
+ success: false,
1891
+ error: 'Limit value must be greater than 0 for Both type'
1892
+ });
1893
+ }
1894
+ if (!premiumExpired) {
1895
+ return res.status(400).json({
1896
+ success: false,
1897
+ error: 'Premium expiration date is required for Both type'
1898
+ });
1899
+ }
1900
+ }
1901
+
1902
+ let premiumExpiredDate = null;
1903
+ if (premiumExpired) {
1904
+ premiumExpiredDate = new Date(premiumExpired);
1905
+ if (premiumExpiredDate <= new Date()) {
1906
+ return res.status(400).json({
1907
+ success: false,
1908
+ error: 'Premium expiration date must be in the future'
1909
+ });
1910
+ }
1911
+ }
1912
+
1913
+ const code = crypto.randomBytes(4).toString('hex').toUpperCase();
1914
+
1915
+ const redeemCode = new RedeemCode({
1916
+ code,
1917
+ type,
1918
+ limitValue: parseInt(limitValue) || 0,
1919
+ codeExpired: codeExpiredDate,
1920
+ premiumExpired: premiumExpiredDate,
1921
+ createdBy: req.user.username
1922
+ });
1923
+
1924
+ await redeemCode.save();
1925
+
1926
+ await logActivity(req.user._id, req.user.username, 'redeem_code_created', `Created redeem code: ${code}`, {
1927
+ code,
1928
+ type,
1929
+ limitValue,
1930
+ codeExpired: codeExpiredDate,
1931
+ premiumExpired: premiumExpiredDate
1932
+ });
1933
+
1934
+ res.json({ success: true, code });
1935
+ } catch (error) {
1936
+ console.error('Redeem code creation error:', error);
1937
+ res.status(500).json({ success: false, error: 'Internal server error' });
1938
+ }
1939
+ });
1940
+
1941
+ app.use('/api', checkBanned);
1942
+ app.use('/api', apiRateLimit);
1943
+
1944
+ let pluginsDir = path.join(__dirname, "plugins");
1945
+ let isJavaScriptFile = (fileName) => /\.js$/.test(fileName);
1946
+ global.plugins = {};
1947
+
1948
+ const loadPlugins = () => {
1949
+ if (!fs.existsSync(pluginsDir)) {
1950
+ console.log('Plugins directory not found, creating...');
1951
+ try {
1952
+ fs.mkdirSync(pluginsDir, { recursive: true });
1953
+ } catch (error) {
1954
+ console.error('Error creating plugins directory:', error);
1955
+ }
1956
+ return;
1957
+ }
1958
+
1959
+ for (let pluginFile of fs.readdirSync(pluginsDir).filter(isJavaScriptFile)) {
1960
+ try {
1961
+ delete require.cache[require.resolve(path.join(pluginsDir, pluginFile))];
1962
+ global.plugins[pluginFile] = require(path.join(pluginsDir, pluginFile));
1963
+ } catch (error) {
1964
+ console.error(`Error loading plugin ${pluginFile}:`, error.message);
1965
+ delete global.plugins[pluginFile];
1966
+ }
1967
+ }
1968
+
1969
+ console.log('Loaded plugins:', Object.keys(global.plugins));
1970
+ };
1971
+
1972
+ global.reload = (event, filename) => {
1973
+ if (/\.js$/.test(filename)) {
1974
+ let fullFilePath = path.join(pluginsDir, filename);
1975
+ if (fullFilePath in require.cache) {
1976
+ delete require.cache[fullFilePath];
1977
+ if (fs.existsSync(fullFilePath)) {
1978
+ console.log(`♻️ Re-requiring plugin '${filename}'`);
1979
+ } else {
1980
+ console.log(`🗑️ Deleted plugin '${filename}'`);
1981
+ return delete global.plugins[filename];
1982
+ }
1983
+ } else {
1984
+ console.log(`🔁 Requiring new plugin '${filename}'`);
1985
+ }
1986
+
1987
+ let errorCheck = syntaxError(fs.readFileSync(fullFilePath), filename);
1988
+ if (errorCheck) {
1989
+ console.error(`❌ Syntax error while loading '${filename}':\n${errorCheck}`);
1990
+ } else {
1991
+ try {
1992
+ global.plugins[filename] = require(fullFilePath);
1993
+ reloadHandler();
1994
+ } catch (error) {
1995
+ console.error(`Error loading plugin ${filename}:`, error);
1996
+ } finally {
1997
+ global.plugins = Object.fromEntries(Object.entries(global.plugins).sort(([a], [b]) => a.localeCompare(b)));
1998
+ }
1999
+ }
2000
+ }
2001
+ };
2002
+
2003
+ const reloadHandler = () => {
2004
+ const routes = [];
2005
+
2006
+ Object.keys(global.plugins).forEach(file => {
2007
+ const plugin = global.plugins[file];
2008
+ if (plugin && plugin.enabled && plugin.routes && plugin.handler) {
2009
+ plugin.routes.forEach(route => {
2010
+ routes.push({ route, plugin, file });
2011
+ });
2012
+ }
2013
+ });
2014
+
2015
+ routes.forEach(({ route, plugin, file }) => {
2016
+ const method = (plugin.type || 'get').toLowerCase();
2017
+ if (app[method] && typeof app[method] === 'function') {
2018
+ app[method](`/${route}`, (req, res, next) => {
2019
+ req.limitDeduction = plugin.limit || 1;
2020
+ next();
2021
+ }, validateApiKey, async (req, res) => {
2022
+ const startTime = Date.now();
2023
+ try {
2024
+ await plugin.handler(req, res);
2025
+
2026
+ await RequestLog.create({
2027
+ userId: req.apiUser._id,
2028
+ username: req.apiUser.username,
2029
+ apikey: req.apiUser.apikey,
2030
+ endpoint: route,
2031
+ ipAddress: req.realIP,
2032
+ userAgent: req.get('User-Agent'),
2033
+ success: true,
2034
+ responseTime: Date.now() - startTime,
2035
+ limitDeducted: req.limitDeducted || 1
2036
+ });
2037
+ } catch (error) {
2038
+ console.error(`Plugin ${plugin.name} error:`, error);
2039
+
2040
+ await RequestLog.create({
2041
+ userId: req.apiUser._id,
2042
+ username: req.apiUser.username,
2043
+ apikey: req.apiUser.apikey,
2044
+ endpoint: route,
2045
+ ipAddress: req.realIP,
2046
+ userAgent: req.get('User-Agent'),
2047
+ success: false,
2048
+ responseTime: Date.now() - startTime,
2049
+ limitDeducted: req.limitDeducted || 1
2050
+ });
2051
+
2052
+ if (!res.headersSent) {
2053
+ res.status(500).json({
2054
  success: false,
2055
+ error: 'Plugin execution failed'
2056
+ });
2057
+ }
2058
+ }
2059
+ });
2060
+ console.log(`✅ Registered route: ${method.toUpperCase()} /${route} from ${file}`);
2061
+ }
2062
+ });
2063
+ };
2064
+
2065
+ Object.freeze(global.reload);
2066
+ fs.watch(pluginsDir, global.reload);
2067
+
2068
+ setInterval(async () => {
2069
+ const now = new Date();
2070
+
2071
+ if (now.getHours() === 0 && now.getMinutes() === 0) {
2072
+ console.log('Running daily limit reset at midnight...');
2073
+
2074
+ try {
2075
+ const users = await User.find({});
2076
+
2077
+ for (const user of users) {
2078
+ await resetUserLimitIfNeeded(user);
2079
+ }
2080
+
2081
+ console.log('Daily limit reset completed for all users');
2082
+ } catch (error) {
2083
+ console.error('Daily reset error:', error);
2084
+ }
2085
+ }
2086
+ }, 60000);
2087
+
2088
+ initializeAdmin();
2089
+ loadPlugins();
2090
+ reloadHandler();
2091
+
2092
+ app.use((err, req, res, next) => {
2093
+ console.error('Unhandled error:', err);
2094
+ res.status(500).json({
2095
+ success: false,
2096
+ error: 'Internal server error'
2097
+ });
2098
+ });
2099
+
2100
+ const PORT = process.env.PORT || 7860;
2101
+ app.listen(PORT, () => {
2102
+ console.log(`DashX API Server running on port ${PORT}`);
2103
+ console.log('=== ADMIN ACCOUNT INFO ===');
2104
+ console.log('Username: HERXA');
2105
+ console.log('Password: BTXHZ');
2106
+ console.log('API Key: DHX-M3SA');
2107
+ console.log('Limit: 9999');
2108
+ console.log('=========================');
2109
+ console.log('Database connected successfully');
2110
+ console.log('Plugin auto-reload enabled');
2111
+ console.log('Daily reset cron job started');
2112
+ });