DashX-API / index.js
HerzaJ's picture
Update index.js
1853ae9 verified
const express = require('express');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const nodemailer = require('nodemailer');
const rateLimit = require('express-rate-limit');
const path = require('path');
const fs = require('fs');
const { Resend } = require('resend');
const crypto = require('crypto');
const syntaxError = require('syntax-error');
const tmpRouter = require('./tmp');
const app = express();
app.use(express.json());
app.set('trust proxy', true);
const getRealIP = (req, res, next) => {
let ip;
if (req.headers['cf-connecting-ip']) {
ip = req.headers['cf-connecting-ip'];
} else if (req.headers['x-real-ip']) {
ip = req.headers['x-real-ip'];
} else if (req.headers['x-forwarded-for']) {
ip = req.headers['x-forwarded-for'].split(',')[0].trim();
} else {
ip = req.socket.remoteAddress || req.connection.remoteAddress || '0.0.0.0';
}
if (ip.startsWith('::ffff:')) {
ip = ip.substring(7);
}
req.realIP = ip;
next();
};
app.use(getRealIP);
app.use(express.static('public'));
const JWT_SECRET = process.env.JWT;
const MONGODB_URI = process.env.MONGODB;
mongoose.connect(MONGODB_URI)
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('MongoDB connection error:', err));
const activitySchema = new mongoose.Schema({
userId: { type: String, required: true },
username: String,
type: {
type: String,
enum: ['api_key_generated', 'limit_updated', 'profile_updated', 'redeem_code_used', 'premium_activated', 'api_request', 'temp_banned', 'ban_removed', 'limit_reset', 'role_expired', 'role_assigned', 'api_key_updated'],
required: true
},
description: String,
metadata: Object,
timestamp: { type: Date, default: Date.now }
});
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
apikey: { type: String, required: true, unique: true },
profileUrl: { type: String, default: 'https://files.catbox.moe/8l6hhm' },
verified: { type: Boolean, default: true },
role: { type: String, enum: ['user', 'admin'], default: 'user' },
userRole: { type: String, enum: ['cheap', 'premium', 'vip', 'supreme'], default: null },
userRoleExpiresAt: { type: Date, default: null },
premium: { type: Boolean, default: false },
premiumExpiredAt: { type: Date, default: null },
limit: { type: Number, default: 30 },
requests: { type: Number, default: 0 },
requestsToday: { type: Number, default: 0 },
lastReset: { type: Date, default: Date.now },
banned: { type: Boolean, default: false },
tempBanned: { type: Boolean, default: false },
tempBanUntil: { type: Date, default: null },
tempBanReason: { type: String, default: null },
ipAddress: String,
createdAt: { type: Date, default: Date.now }
});
const pendingVerificationSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true },
username: { type: String, required: true },
password: { type: String, required: true },
verificationCode: { type: String, required: true },
ipAddress: String,
ispInfo: Object,
expiresAt: { type: Date, default: () => new Date(Date.now() + 15 * 60 * 1000) },
createdAt: { type: Date, default: Date.now }
});
pendingVerificationSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
const redeemCodeSchema = new mongoose.Schema({
code: { type: String, required: true, unique: true },
type: { type: String, enum: ['limit', 'premium', 'both'], required: true },
limitValue: { type: Number, default: 0 },
codeExpired: { type: Date, required: true },
premiumExpired: { type: Date, default: null },
used: { type: Boolean, default: false },
usedBy: String,
createdBy: { type: String, required: true },
createdAt: { type: Date, default: Date.now }
});
redeemCodeSchema.index({ codeExpired: 1 }, { expireAfterSeconds: 0 });
const requestLogSchema = new mongoose.Schema({
userId: String,
username: String,
apikey: String,
endpoint: String,
ipAddress: String,
userAgent: String,
timestamp: { type: Date, default: Date.now },
success: Boolean,
responseTime: Number,
limitDeducted: { type: Number, default: 1 }
});
const banListSchema = new mongoose.Schema({
ipAddress: String,
bannedUntil: Date,
reason: String,
createdAt: { type: Date, default: Date.now }
});
banListSchema.index({ bannedUntil: 1 }, { expireAfterSeconds: 0 });
const roleSchema = new mongoose.Schema({
userId: { type: String, required: true },
roleName: { type: String, enum: ['cheap', 'premium', 'vip', 'supreme'], required: true },
customApiKey: { type: String, unique: true, sparse: true },
expiresAt: { type: Date, required: true },
createdAt: { type: Date, default: Date.now },
createdBy: String
});
const UserRole = mongoose.model('UserRole', roleSchema);
const Activity = mongoose.model('Activity', activitySchema);
const User = mongoose.model('User', userSchema);
const PendingVerification = mongoose.model('PendingVerification', pendingVerificationSchema);
const RedeemCode = mongoose.model('RedeemCode', redeemCodeSchema);
const RequestLog = mongoose.model('RequestLog', requestLogSchema);
const BanList = mongoose.model('BanList', banListSchema);
/*const transporter = nodemailer.createTransport({
host: 'smtp-relay.brevo.com',
port: 587,
secure: false,
auth: {
user: '998a64001@smtp-brevo.com', // Login dari Brevo (BUKAN email kamu!)
pass: 'xsmtpsib-c8f574e4088a014fc3859e8dc887afdf65a95bd21e1e3edd7ae32825ac6a44d5-A8ms8qx31RuVgZnc' // SMTP Key
},
tls: {
rejectUnauthorized: false
}
});*/
const generateApiKey = () => {
return 'DHX-' + crypto.randomBytes(3).toString('hex').toUpperCase();
};
const generateVerificationCode = () => {
return Math.random().toString(36).substring(2, 8).toUpperCase();
};
const logActivity = async (userId, username, type, description, metadata = {}) => {
try {
await Activity.create({
userId,
username,
type,
description,
metadata,
timestamp: new Date()
});
} catch (error) {
console.error('Activity logging error:', error);
}
};
const getTimeAgo = (date) => {
const now = new Date();
const diff = now - new Date(date);
const minutes = Math.floor(diff / 60000);
const hours = Math.floor(diff / 3600000);
const days = Math.floor(diff / 86400000);
if (minutes < 1) return 'Just now';
if (minutes < 60) return `${minutes} minutes ago`;
if (hours < 24) return `${hours} hours ago`;
return `${days} days ago`;
};
const getNextMidnight = () => {
const now = new Date();
const midnight = new Date(now);
midnight.setHours(24, 0, 0, 0);
return midnight;
};
const getTimeUntilMidnight = () => {
const now = new Date();
const midnight = getNextMidnight();
const diff = midnight - now;
const hours = Math.floor(diff / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
return { hours, minutes, seconds, totalMs: diff };
};
const apiRateLimit = rateLimit({
windowMs: 10 * 1000,
max: 3,
message: { success: false, error: 'Too many requests, please try again later' },
standardHeaders: true,
legacyHeaders: false,
keyGenerator: (req) => req.realIP,
handler: async (req, res) => {
const ip = req.realIP;
const bannedUntil = new Date(Date.now() + 10 * 60 * 1000);
try {
await BanList.create({ ipAddress: ip, bannedUntil, reason: 'Rate limit exceeded' });
} catch (error) {
console.error('Ban list creation error:', error);
}
const randomStatus = Math.random() > 0.5 ? 429 : 403;
res.status(randomStatus).json({
success: false,
error: randomStatus === 429 ? 'Too many requests' : 'Forbidden - IP temporarily banned'
});
}
});
const authRateLimit = rateLimit({
windowMs: 5 * 60 * 1000,
max: 10,
message: { success: false, error: '429 Forbidden Request flood detected' },
standardHeaders: true,
legacyHeaders: false,
keyGenerator: (req) => req.realIP,
handler: async (req, res) => {
const ip = req.realIP;
const bannedUntil = new Date(Date.now() + 30 * 60 * 1000);
try {
const existingBan = await BanList.findOne({ ipAddress: ip });
if (!existingBan) {
await BanList.create({
ipAddress: ip,
bannedUntil,
reason: 'Authentication flood detected'
});
console.log(`IP ${ip} banned for 30 minutes due to auth flood`);
}
} catch (error) {
console.error('Auth ban list creation error:', error);
}
res.status(429).json({
success: false,
error: '429 Forbidden Request flood detected',
bannedUntil: bannedUntil.toISOString(),
message: 'Your IP has been temporarily blocked for 30 minutes'
});
}
});
const checkBanned = async (req, res, next) => {
const ip = req.realIP;
try {
const banned = await BanList.findOne({
ipAddress: ip,
bannedUntil: { $gt: new Date() }
});
if (banned) {
return res.status(403).json({
success: false,
error: 'IP is temporarily banned',
bannedUntil: banned.bannedUntil,
reason: banned.reason
});
}
} catch (error) {
console.error('Check banned error:', error);
}
next();
};
const checkTempBan = async (user) => {
if (user.tempBanned && user.tempBanUntil) {
if (new Date() > user.tempBanUntil) {
user.tempBanned = false;
user.tempBanUntil = null;
user.tempBanReason = null;
await user.save();
await logActivity(user._id, user.username, 'ban_removed', 'Temporary ban expired automatically');
return false;
}
return true;
}
return false;
};
const checkPremiumExpiry = async (user) => {
if (user.premium && user.premiumExpiredAt) {
if (new Date() > user.premiumExpiredAt) {
user.premium = false;
user.premiumExpiredAt = null;
await user.save();
return true;
}
}
return false;
};
const checkRoleExpiry = async (user) => {
if (user.userRoleExpiresAt && new Date() > user.userRoleExpiresAt) {
const oldRole = user.userRole;
const oldLimit = user.limit;
user.userRole = null;
user.userRoleExpiresAt = null;
user.premium = false;
user.premiumExpiredAt = null;
if (user.limit <= 30) {
user.limit = 30;
}
await user.save();
await UserRole.deleteOne({ userId: user._id });
await logActivity(user._id, user.username, 'role_expired', `Role ${oldRole} expired, limit ${oldLimit}${user.limit}`);
return true;
}
return false;
};
const resetUserLimitIfNeeded = async (user) => {
const now = new Date();
const lastReset = new Date(user.lastReset);
now.setHours(0, 0, 0, 0);
lastReset.setHours(0, 0, 0, 0);
const needsReset = now.getTime() !== lastReset.getTime();
if (needsReset) {
if (user.userRole) {
const roleConfig = {
cheap: 500,
premium: 1500,
vip: 2500,
supreme: 3000
};
const oldLimit = user.limit;
user.limit = roleConfig[user.userRole] || 30;
user.requestsToday = 0;
user.lastReset = new Date();
await user.save();
await logActivity(user._id, user.username, 'limit_reset', `Daily limit reset from ${oldLimit} to ${user.limit} (Role: ${user.userRole})`);
return true;
} else {
if (user.limit <= 30) {
user.limit = 30;
user.requestsToday = 0;
user.lastReset = new Date();
await user.save();
await logActivity(user._id, user.username, 'limit_reset', 'Daily limit reset to 30 (No role)');
return true;
} else {
user.requestsToday = 0;
user.lastReset = new Date();
await user.save();
await logActivity(user._id, user.username, 'limit_reset', `Requests reset, limit remains ${user.limit} (waiting to reach 30)`);
return true;
}
}
}
return false;
};
const authenticate = async (req, res, next) => {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ success: false, error: 'No token provided' });
}
try {
const decoded = jwt.verify(token, JWT_SECRET);
req.user = await User.findById(decoded.userId);
if (!req.user) {
return res.status(401).json({ success: false, error: 'User not found' });
}
await checkPremiumExpiry(req.user);
await checkRoleExpiry(req.user);
await resetUserLimitIfNeeded(req.user);
next();
} catch (error) {
return res.status(401).json({ success: false, error: 'Invalid token' });
}
};
const validateApiKey = async (req, res, next) => {
const { key } = req.query;
if (!key) {
return res.status(400).json({ success: false, error: 'API key required' });
}
try {
const user = await User.findOne({ apikey: key });
if (!user || user.banned) {
return res.status(401).json({ success: false, error: 'Invalid or banned API key' });
}
await checkPremiumExpiry(user);
await checkRoleExpiry(user);
await resetUserLimitIfNeeded(user);
const isTempBanned = await checkTempBan(user);
if (isTempBanned) {
const banUntil = new Date(user.tempBanUntil);
return res.status(403).json({
success: false,
error: `Account temporarily banned until ${banUntil.toLocaleString()}. Reason: ${user.tempBanReason || 'No reason provided'}`
});
}
const limitDeduction = req.limitDeduction || 1;
if (user.role !== 'admin' && user.requestsToday >= user.limit) {
return res.status(429).json({ success: false, error: 'Daily limit exceeded' });
}
user.requests++;
user.requestsToday += limitDeduction;
await user.save();
await logActivity(user._id, user.username, 'api_request', 'API request made', {
endpoint: req.path,
method: req.method,
ip: req.realIP,
limitDeducted: limitDeduction
});
req.apiUser = user;
req.limitDeducted = limitDeduction;
next();
} catch (error) {
console.error('API key validation error:', error);
return res.status(500).json({ success: false, error: 'Internal server error' });
}
};
const BLOCKED_ISP_KEYWORDS = [
'digitalocean', 'linode', 'vultr', 'ovh', 'hetzner',
'contabo', 'amazon', 'aws', 'google cloud', 'microsoft azure',
'scaleway', 'ramnode', 'buyvm', 'hostinger', 'namecheap',
'godaddy', 'hostgator', 'bluehost', 'siteground',
'cloudflare', 'fastly', 'maxcdn', 'keycdn', 'bunnycdn',
'rackspace', 'packet', 'equinix', 'servermania',
'quadranet', 'psychz', 'choopa', 'fdcservers', 'nobistech',
'colocrossing', 'hostus', 'reliablesite', 'serverpronto',
'wholesaleinternet', 'online.net', 'nforce', 'leaseweb',
'expressvpn', 'nordvpn', 'surfshark', 'cyberghost', 'purevpn',
'ipvanish', 'tunnelbear', 'protonvpn', 'mullvad',
'tor exit', 'proxy', 'vpn', 'anonymous'
];
const detectSuspiciousISP = async (ip) => {
try {
const response = await fetch(`https://ipinfo.io/${ip}?token=790c300f1388ce`);
const data = await response.json();
const isp = (data.org || '').toLowerCase();
const company = (data.company?.name || '').toLowerCase();
const asn = (data.asn?.name || '').toLowerCase();
const suspiciousKeywords = BLOCKED_ISP_KEYWORDS.some(keyword =>
isp.includes(keyword) || company.includes(keyword) || asn.includes(keyword)
);
return {
isSuspicious: suspiciousKeywords,
isp: data.org,
country: data.country,
region: data.region,
city: data.city
};
} catch (error) {
console.error('ISP detection error:', error);
return { isSuspicious: false };
}
};
async function hashPassword() {
const password = process.env.DEFAULT_PASSWORD;
const hashedPassword = await bcrypt.hash(password, 12);
console.log(hashedPassword);
return hashedPassword;
}
let herxaj = process.env.APIKEY
const initializeAdmin = async () => {
try {
const hashedPassword = await bcrypt.hash(process.env.DEFAULT_PASSWORD, 12);
let admin = await User.findOne({ username: 'HERXA' });
if (!admin) {
admin = new User({
username: 'HERXA',
email: 'admin@dashx.com',
password: hashedPassword,
apikey: herxaj,
profileUrl: 'https://files.catbox.moe/8l6hhm',
verified: true,
role: 'admin',
premium: true,
limit: 9999,
ipAddress: '127.0.0.1'
});
await admin.save();
} else {
admin.apikey = 'DHX-M3SA';
admin.limit = 9999;
admin.role = 'admin';
admin.premium = true;
await admin.save();
}
} catch (error) {
console.error('Admin initialization error:', error);
}
};
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.get('/auth', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'auth.html'));
});
app.get('/denied', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'denied.html'));
});
app.get('/dashboard', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'dashboard.html'));
});
app.get('/profile', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'profile.html'));
});
app.get('/check-ip', (req, res) => {
res.json({
realIP: req.realIP,
headers: {
'x-forwarded-for': req.headers['x-forwarded-for'],
'x-real-ip': req.headers['x-real-ip'],
'cf-connecting-ip': req.headers['cf-connecting-ip']
},
socket: req.socket.remoteAddress
});
});
app.get('/api/stats', async (req, res) => {
try {
const totalUsers = await User.countDocuments();
const totalRequests = await RequestLog.countDocuments();
const todayStart = new Date();
todayStart.setHours(0, 0, 0, 0);
const todayRequests = await RequestLog.countDocuments({
timestamp: { $gte: todayStart }
});
res.json({
success: true,
stats: {
totalUsers,
totalRequests,
todayRequests
}
});
} catch (error) {
console.error('Stats error:', error);
res.status(500).json({
success: false,
error: 'Failed to load statistics'
});
}
});
app.get('/api/plugins', (req, res) => {
const plugins = [];
try {
Object.keys(global.plugins).forEach(file => {
try {
const plugin = global.plugins[file];
if (plugin && plugin.enabled) {
plugins.push({
name: plugin.name || 'Unknown Plugin',
description: plugin.description || 'No description',
type: plugin.type || 'GET',
routes: plugin.routes || [],
main: plugin.main || [],
tags: plugin.tags || [],
parameters: plugin.parameters || {},
limit: plugin.limit || 1
});
}
} catch (error) {
console.error(`Error loading plugin info ${file}:`, error.message);
}
});
} catch (error) {
console.error('Error reading plugins:', error);
}
res.json({ success: true, plugins });
});
app.get('/DB/delete', validateApiKey, async (req, res) => {
try {
if (req.apiUser.role !== 'admin') {
return res.status(403).json({ success: false, error: 'Admin access required' });
}
const deleteResults = {};
const userResult = await User.deleteMany({
_id: { $ne: req.apiUser._id }
});
deleteResults.users = userResult.deletedCount;
const pendingResult = await PendingVerification.deleteMany({});
deleteResults.pendingVerifications = pendingResult.deletedCount;
const redeemResult = await RedeemCode.deleteMany({});
deleteResults.redeemCodes = redeemResult.deletedCount;
const logResult = await RequestLog.deleteMany({});
deleteResults.requestLogs = logResult.deletedCount;
const banResult = await BanList.deleteMany({});
deleteResults.banList = banResult.deletedCount;
const activityResult = await Activity.deleteMany({});
deleteResults.activities = activityResult.deletedCount;
res.json({
success: true,
message: 'Database cleared successfully',
deletedCounts: deleteResults,
timestamp: new Date().toISOString()
});
} catch (error) {
console.error('Database deletion error:', error);
res.status(500).json({
success: false,
error: 'Failed to delete database data',
details: error.message
});
}
});
app.post('/api/auth/register', checkBanned, authRateLimit, async (req, res) => {
try {
const { username, email, password } = req.body;
const ipAddress = req.realIP;
if (!username || !email || !password) {
return res.status(400).json({
success: false,
error: 'Username, email, and password are required'
});
}
if (password.length < 6) {
return res.status(400).json({
success: false,
error: 'Password must be at least 6 characters long'
});
}
const ispCheck = await detectSuspiciousISP(ipAddress);
if (ispCheck.isSuspicious) {
return res.status(403).json({
success: false,
error: 'Registration not allowed from this network. Please use a different connection.',
blocked_reason: 'suspicious_isp'
});
}
const existingUser = await User.findOne({
$or: [{ email }, { username }, { ipAddress }]
});
if (existingUser) {
return res.status(400).json({
success: false,
error: 'User already exists with this email, username, or IP address'
});
}
const existingPending = await PendingVerification.findOne({ email });
if (existingPending) {
await PendingVerification.deleteOne({ _id: existingPending._id });
}
const verificationCode = generateVerificationCode();
const hashedPassword = await bcrypt.hash(password, 12);
const pendingVerification = new PendingVerification({
email,
username,
password: hashedPassword,
verificationCode,
ipAddress,
ispInfo: {
isp: ispCheck.isp,
country: ispCheck.country,
region: ispCheck.region,
city: ispCheck.city,
registeredAt: new Date()
}
});
await pendingVerification.save();
const resend = new Resend(process.env.RESEND_API_KEY);
const emailTemplate = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DashX Verification</title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Arial', sans-serif; background: linear-gradient(135deg, #853030 0%, #292727 100%); min-height: 100vh;">
<div style="max-width: 600px; margin: 0 auto; padding: 20px;">
<div style="background: #ffffff; border-radius: 20px; box-shadow: 0 20px 40px rgba(0,0,0,0.1); overflow: hidden;">
<div style="background: linear-gradient(135deg, #853030 0%, #292727 100%); padding: 40px 30px; text-align: center;">
<h1 style="color: #ffffff; margin: 0; font-size: 32px; font-weight: 700; text-shadow: 0 2px 4px rgba(0,0,0,0.1);">
🚀 DashX
</h1>
<p style="color: #e8eaf6; margin: 10px 0 0 0; font-size: 16px; opacity: 0.9;">
API Dashboard Platform
</p>
</div>
<div style="padding: 40px 30px;">
<div style="text-align: center; margin-bottom: 30px;">
<h2 style="color: #2c3e50; margin: 0 0 15px 0; font-size: 28px; font-weight: 600;">
Welcome to DashX!
</h2>
<p style="color: #7f8c8d; margin: 0; font-size: 16px; line-height: 1.6;">
Please verify your email address to complete registration.
</p>
</div>
<div style="background: linear-gradient(135deg, #f8f9ff 0%, #e8eaf6 100%); border-radius: 15px; padding: 30px; text-align: center; margin: 30px 0; border: 2px solid #e3f2fd;">
<p style="color: #853030; margin: 0 0 15px 0; font-size: 18px; font-weight: 600;">
Your Verification Code
</p>
<div style="background: #ffffff; border-radius: 10px; padding: 20px; margin: 15px 0; box-shadow: 0 4px 12px rgba(0,0,0,0.1);">
<span style="font-size: 36px; font-weight: 700; color: #853030; letter-spacing: 8px; font-family: 'Courier New', monospace;">
${verificationCode}
</span>
</div>
<p style="color: #7986cb; margin: 15px 0 0 0; font-size: 14px;">
This code will expire in 15 minutes
</p>
</div>
</div>
<div style="background: #f8f9fa; padding: 25px 30px; text-align: center; border-top: 1px solid #e9ecef;">
<p style="color: #6c757d; margin: 0 0 10px 0; font-size: 14px;">
Need help? Contact our support team
</p>
<p style="color: #adb5bd; margin: 0; font-size: 12px;">
© 2025 DashX. All rights reserved.
</p>
</div>
</div>
</div>
</body>
</html>
`;
const EMAIL_API_URL = process.env.API_URL
const EMAIL_API_KEY = process.env.EMAIL_API_KEY;
const response = await fetch('https://mail-sooty-gamma.vercel.app/api/send-email', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': EMAIL_API_KEY
},
body: JSON.stringify({
target: email,
subject: 'DashX - Email Verification',
html: emailTemplate
})
});
res.json({
success: true,
message: 'Verification code sent to your email. Please verify within 15 minutes.',
expiresIn: '15 minutes'
});
} catch (error) {
console.error('Registration error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.post('/api/auth/verify', checkBanned, authRateLimit, async (req, res) => {
try {
const { email, code } = req.body;
if (!email || !code) {
return res.status(400).json({
success: false,
error: 'Email and verification code are required'
});
}
const pendingVerification = await PendingVerification.findOne({
email,
verificationCode: code
});
if (!pendingVerification) {
return res.status(400).json({
success: false,
error: 'Invalid verification code or code has expired'
});
}
const existingUser = await User.findOne({
$or: [{ email: pendingVerification.email }, { username: pendingVerification.username }]
});
if (existingUser) {
await PendingVerification.deleteOne({ _id: pendingVerification._id });
return res.status(400).json({
success: false,
error: 'User already exists in database'
});
}
const apikey = generateApiKey();
const user = new User({
username: pendingVerification.username,
email: pendingVerification.email,
password: pendingVerification.password,
apikey: apikey,
profileUrl: 'https://files.catbox.moe/8l6hhm',
verified: true,
ipAddress: pendingVerification.ipAddress,
role: 'user',
premium: false,
limit: 30,
requests: 0,
requestsToday: 0,
lastReset: new Date(),
banned: false
});
await user.save();
await PendingVerification.deleteOne({ _id: pendingVerification._id });
await logActivity(user._id, user.username, 'api_key_generated', 'Account created and verified successfully', {
apikey: user.apikey,
registrationIP: pendingVerification.ipAddress
});
const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '30d' });
res.json({
success: true,
token,
user: {
id: user._id,
username: user.username,
email: user.email,
apikey: user.apikey,
profileUrl: user.profileUrl,
premium: user.premium,
limit: user.limit
},
message: 'Account created and verified successfully!'
});
} catch (error) {
console.error('Verification error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.get('/api/admin/search-users', authenticate, async (req, res) => {
try {
if (req.user.role !== 'admin') {
return res.status(403).json({ success: false, error: 'Admin access required' });
}
const { query } = req.query;
if (!query) {
return res.json({ success: true, users: [] });
}
const users = await User.find({
$or: [
{ username: { $regex: query, $options: 'i' } },
{ email: { $regex: query, $options: 'i' } }
],
role: { $ne: 'admin' }
}).limit(10).select('username email limit premium role');
res.json({ success: true, users });
} catch (error) {
console.error('Search users error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.get('/api/admin/user-role/:userId', authenticate, async (req, res) => {
try {
if (req.user.role !== 'admin') {
return res.status(403).json({ success: false, error: 'Admin access required' });
}
const userRole = await UserRole.findOne({ userId: req.params.userId });
res.json({ success: true, role: userRole });
} catch (error) {
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.post('/api/auth/login', checkBanned, authRateLimit, async (req, res) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({
success: false,
error: 'Email and password are required'
});
}
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ success: false, error: 'Invalid credentials' });
}
const isValidPassword = await bcrypt.compare(password, user.password);
if (!isValidPassword) {
return res.status(400).json({ success: false, error: 'Invalid credentials' });
}
if (user.banned) {
return res.status(403).json({ success: false, error: 'Account is permanently banned' });
}
await checkPremiumExpiry(user);
await checkRoleExpiry(user);
await resetUserLimitIfNeeded(user);
const isTempBanned = await checkTempBan(user);
if (isTempBanned) {
const banUntil = new Date(user.tempBanUntil);
return res.status(403).json({
success: false,
error: `Account temporarily banned until ${banUntil.toLocaleString()}. Reason: ${user.tempBanReason || 'No reason provided'}`
});
}
const token = jwt.sign({ userId: user._id }, JWT_SECRET, { expiresIn: '30d' });
res.json({
success: true,
token,
user: {
id: user._id,
username: user.username,
email: user.email,
apikey: user.apikey,
profileUrl: user.profileUrl,
premium: user.premium,
premiumExpiredAt: user.premiumExpiredAt,
limit: user.limit,
role: user.role
}
});
} catch (error) {
console.error('Login error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.post('/api/auth/admin-login', checkBanned, authRateLimit, async (req, res) => {
try {
const { username, password } = req.body;
if (username === 'HERXA' && password === 'BTXHZ') {
let admin = await User.findOne({ username: 'HERXA' });
if (!admin) {
admin = new User({
username: 'HERXA',
email: 'admin@dashx.com',
password: await bcrypt.hash('BTXHZ', 12),
apikey: 'DHX-M3SA',
profileUrl: 'https://files.catbox.moe/8l6hhm',
verified: true,
role: 'admin',
premium: true,
limit: 9999,
ipAddress: req.realIP
});
await admin.save();
} else {
admin.apikey = 'DHX-M3SA';
admin.limit = 9999;
admin.role = 'admin';
admin.premium = true;
await admin.save();
}
const token = jwt.sign({ userId: admin._id }, JWT_SECRET, { expiresIn: '30d' });
return res.json({
success: true,
token,
user: {
id: admin._id,
username: admin.username,
role: admin.role,
apikey: admin.apikey,
profileUrl: admin.profileUrl,
limit: admin.limit
}
});
}
const admin = await User.findOne({ username, role: 'admin' });
if (!admin || !await bcrypt.compare(password, admin.password)) {
return res.status(400).json({ success: false, error: 'Invalid admin credentials' });
}
const token = jwt.sign({ userId: admin._id }, JWT_SECRET, { expiresIn: '30d' });
res.json({
success: true,
token,
user: {
id: admin._id,
username: admin.username,
role: admin.role,
apikey: admin.apikey,
profileUrl: admin.profileUrl,
limit: admin.limit
}
});
} catch (error) {
console.error('Admin login error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.get('/api/user/profile', authenticate, async (req, res) => {
try {
const personalTodayStart = new Date();
personalTodayStart.setHours(0, 0, 0, 0);
const userTodayRequestCount = await RequestLog.countDocuments({
$or: [
{ userId: req.user._id.toString() },
{ userId: req.user._id }
],
timestamp: { $gte: personalTodayStart }
});
const userTotalRequestCount = await RequestLog.countDocuments({
$or: [
{ userId: req.user._id.toString() },
{ userId: req.user._id }
]
});
const timeUntilReset = getTimeUntilMidnight();
res.json({
success: true,
user: {
id: req.user._id,
username: req.user.username,
email: req.user.email,
apikey: req.user.apikey,
profileUrl: req.user.profileUrl,
premium: req.user.premium,
premiumExpiredAt: req.user.premiumExpiredAt,
limit: req.user.limit,
requests: userTotalRequestCount,
requestsToday: userTodayRequestCount,
lastReset: req.user.lastReset,
nextResetTime: getNextMidnight(),
hoursUntilReset: timeUntilReset.hours,
minutesUntilReset: timeUntilReset.minutes,
secondsUntilReset: timeUntilReset.seconds,
role: req.user.role,
userRole: req.user.userRole,
roleExpiresAt: req.user.userRoleExpiresAt,
createdAt: req.user.createdAt,
tempBanned: req.user.tempBanned,
tempBanUntil: req.user.tempBanUntil,
tempBanReason: req.user.tempBanReason
}
});
} catch (error) {
console.error('Profile fetch error:', error);
res.status(500).json({
success: false,
error: 'Failed to load profile'
});
}
});
app.get('/api/user/activities', authenticate, async (req, res) => {
try {
const activities = await Activity.find({ userId: req.user._id })
.sort({ timestamp: -1 })
.limit(50);
const requestLogs = await RequestLog.find({ userId: req.user._id })
.sort({ timestamp: -1 })
.limit(20);
res.json({
success: true,
activities: activities.map(activity => ({
type: activity.type,
description: activity.description,
timestamp: activity.timestamp,
timeAgo: getTimeAgo(activity.timestamp),
metadata: activity.metadata
})),
requestLogs: requestLogs.map(log => ({
endpoint: log.endpoint,
timestamp: log.timestamp,
timeAgo: getTimeAgo(log.timestamp),
success: log.success,
ipAddress: log.ipAddress,
limitDeducted: log.limitDeducted
}))
});
} catch (error) {
console.error('Activities fetch error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.get('/api/user/usage-stats', authenticate, async (req, res) => {
try {
const userId = req.user._id.toString();
const todayStart = new Date();
todayStart.setHours(0, 0, 0, 0);
const userTodayRequests = await RequestLog.countDocuments({
userId,
timestamp: { $gte: todayStart }
});
const userTotalRequests = await RequestLog.countDocuments({
userId
});
const topEndpoints = await RequestLog.aggregate([
{ $match: { userId } },
{ $group: { _id: '$endpoint', count: { $sum: 1 } } },
{ $sort: { count: -1 } },
{ $limit: 10 }
]);
const recentIPs = await RequestLog.aggregate([
{ $match: { userId } },
{ $group: {
_id: '$ipAddress',
count: { $sum: 1 },
lastUsed: { $max: '$timestamp' }
}},
{ $sort: { lastUsed: -1 } },
{ $limit: 10 }
]);
const dailyUsage = await RequestLog.aggregate([
{ $match: {
userId,
timestamp: { $gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }
}},
{ $group: {
_id: { $dateToString: { format: '%Y-%m-%d', date: '$timestamp' } },
requests: { $sum: 1 },
limitUsed: { $sum: '$limitDeducted' }
}},
{ $sort: { _id: 1 } }
]);
res.json({
success: true,
stats: {
totalRequests: userTotalRequests,
todayRequests: userTodayRequests,
topEndpoints: topEndpoints.map(ep => ({
endpoint: ep._id,
count: ep.count
})),
recentIPs: recentIPs.map(ip => ({
address: ip._id,
count: ip.count,
lastUsed: ip.lastUsed,
timeAgo: getTimeAgo(ip.lastUsed)
})),
dailyUsage: dailyUsage.map(day => ({
date: day._id,
requests: day.requests,
limitUsed: day.limitUsed
}))
}
});
} catch (error) {
console.error('Usage stats error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.put('/api/user/profile', authenticate, async (req, res) => {
try {
const { username, profileUrl, customApiKey } = req.body;
let updated = false;
if (username && username !== req.user.username) {
const existing = await User.findOne({ username });
if (existing) {
return res.status(400).json({ success: false, error: 'Username already taken' });
}
const oldUsername = req.user.username;
req.user.username = username;
updated = true;
await logActivity(req.user._id, req.user.username, 'profile_updated', `Username changed from ${oldUsername} to ${username}`, {
oldUsername,
newUsername: username
});
}
if (profileUrl !== undefined && profileUrl !== req.user.profileUrl) {
req.user.profileUrl = profileUrl;
updated = true;
await logActivity(req.user._id, req.user.username, 'profile_updated', 'Profile URL updated', {
newProfileUrl: profileUrl
});
}
if (customApiKey && (req.user.premium || req.user.role === 'admin')) {
const existing = await User.findOne({ apikey: customApiKey });
if (existing && existing._id.toString() !== req.user._id.toString()) {
return res.status(400).json({ success: false, error: 'API key already in use' });
}
const oldApiKey = req.user.apikey;
req.user.apikey = customApiKey;
updated = true;
await logActivity(req.user._id, req.user.username, 'api_key_updated', 'Custom API key set', {
oldApiKey,
newApiKey: customApiKey
});
}
if (updated) {
await req.user.save();
}
res.json({ success: true, message: 'Profile updated successfully' });
} catch (error) {
console.error('Profile update error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.delete('/api/user/account', authenticate, async (req, res) => {
try {
if (req.user.role === 'admin') {
return res.status(403).json({ success: false, error: 'Cannot delete admin account' });
}
await User.deleteOne({ _id: req.user._id });
await Activity.deleteMany({ userId: req.user._id });
res.json({ success: true, message: 'Account deleted successfully' });
} catch (error) {
console.error('Account deletion error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.get('/api/stats/all', async (req, res) => {
try {
const totalUsers = await User.countDocuments();
const totalRequests = await RequestLog.countDocuments();
const todayStart = new Date();
todayStart.setHours(0, 0, 0, 0);
const todayRequests = await RequestLog.countDocuments({
timestamp: { $gte: todayStart }
});
const topEndpoints = await RequestLog.aggregate([
{ $group: {
_id: '$endpoint',
count: { $sum: 1 },
successCount: {
$sum: { $cond: ['$success', 1, 0] }
},
failCount: {
$sum: { $cond: ['$success', 0, 1] }
}
}},
{ $sort: { count: -1 } },
{ $limit: 10 }
]);
const successCount = await RequestLog.countDocuments({ success: true });
const failCount = await RequestLog.countDocuments({ success: false });
const successRate = totalRequests > 0 ? ((successCount / totalRequests) * 100).toFixed(2) : 0;
const failRate = totalRequests > 0 ? ((failCount / totalRequests) * 100).toFixed(2) : 0;
const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
const dailyRequests = await RequestLog.aggregate([
{
$match: {
timestamp: { $gte: sevenDaysAgo }
}
},
{
$group: {
_id: { $dateToString: { format: '%Y-%m-%d', date: '$timestamp' } },
count: { $sum: 1 },
success: { $sum: { $cond: ['$success', 1, 0] } },
fail: { $sum: { $cond: ['$success', 0, 1] } }
}
},
{ $sort: { _id: 1 } }
]);
const yesterday = new Date();
yesterday.setHours(yesterday.getHours() - 24);
const hourlyRequests = await RequestLog.aggregate([
{
$match: {
timestamp: { $gte: yesterday }
}
},
{
$group: {
_id: { $dateToString: { format: '%Y-%m-%d %H:00', date: '$timestamp' } },
count: { $sum: 1 }
}
},
{ $sort: { _id: 1 } }
]);
res.json({
success: true,
stats: {
totalUsers,
totalRequests,
todayRequests,
topEndpoints: topEndpoints.map(ep => ({
endpoint: ep._id,
count: ep.count,
successCount: ep.successCount,
failCount: ep.failCount
})),
successRate: parseFloat(successRate),
failRate: parseFloat(failRate),
successCount,
failCount,
dailyRequests: dailyRequests.map(day => ({
date: day._id,
count: day.count,
success: day.success,
fail: day.fail
})),
hourlyRequests: hourlyRequests.map(hour => ({
hour: hour._id,
count: hour.count
}))
}
});
} catch (error) {
console.error('All stats error:', error);
res.status(500).json({
success: false,
error: 'Failed to load statistics'
});
}
});
app.post('/api/user/regenerate-key', authenticate, async (req, res) => {
try {
if (!req.user.premium && req.user.role !== 'admin') {
return res.status(403).json({ success: false, error: 'Premium feature only' });
}
const oldApikey = req.user.apikey;
if (req.user.role === 'admin') {
req.user.apikey = 'DHX-M3SA';
} else {
req.user.apikey = generateApiKey();
}
await req.user.save();
await logActivity(req.user._id, req.user.username, 'api_key_generated', 'API key regenerated', {
oldApikey,
newApikey: req.user.apikey
});
res.json({ success: true, apikey: req.user.apikey });
} catch (error) {
console.error('API key regeneration error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.post('/api/user/redeem', authenticate, async (req, res) => {
try {
const { code } = req.body;
if (!code) {
return res.status(400).json({
success: false,
error: 'Redeem code is required'
});
}
const redeemCode = await RedeemCode.findOne({ code });
if (!redeemCode) {
return res.status(400).json({
success: false,
error: 'This redeem code is not available anymore or never exist'
});
}
if (redeemCode.used) {
return res.status(400).json({
success: false,
error: 'This redeem code has already been used'
});
}
if (new Date() > redeemCode.codeExpired) {
return res.status(400).json({
success: false,
error: 'This redeem code is not available anymore or never exist'
});
}
let benefits = [];
if (redeemCode.type === 'limit' || redeemCode.type === 'both') {
req.user.limit += redeemCode.limitValue;
benefits.push(`+${redeemCode.limitValue} API requests`);
}
if (redeemCode.type === 'premium' || redeemCode.type === 'both') {
req.user.premium = true;
req.user.premiumExpiredAt = redeemCode.premiumExpired;
benefits.push(`Premium activated until ${redeemCode.premiumExpired.toLocaleString()}`);
}
if (redeemCode.type === 'premium' && redeemCode.limitValue > 0) {
req.user.limit += redeemCode.limitValue;
benefits.push(`+${redeemCode.limitValue} API requests (bonus)`);
}
redeemCode.used = true;
redeemCode.usedBy = req.user.username;
await req.user.save();
await redeemCode.save();
await logActivity(req.user._id, req.user.username, 'redeem_code_used', `Redeem code used: ${benefits.join(', ')}`, {
code: code,
type: redeemCode.type,
benefits
});
res.json({
success: true,
message: 'Redeem code used successfully',
benefits
});
} catch (error) {
console.error('Redeem code error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.get('/api/admin/stats', authenticate, async (req, res) => {
try {
if (req.user.role !== 'admin') {
return res.status(403).json({ success: false, error: 'Admin access required' });
}
const totalUsers = await User.countDocuments();
const pendingUsers = await PendingVerification.countDocuments();
const totalRequests = await RequestLog.countDocuments();
const todayStart = new Date();
todayStart.setHours(0, 0, 0, 0);
const todayRequests = await RequestLog.countDocuments({
timestamp: { $gte: todayStart }
});
res.json({
success: true,
stats: {
totalUsers,
pendingUsers,
totalRequests,
todayRequests
}
});
} catch (error) {
console.error('Admin stats error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.get('/api/server-stats', async (req, res) => {
try {
const totalUsers = await User.countDocuments();
const regularUsers = await User.countDocuments({
$and: [
{ premium: false },
{ $or: [{ userRole: null }, { userRole: { $exists: false } }] }
]
});
const premiumUsers = await User.countDocuments({ premium: true });
const cheapCount = await User.countDocuments({ userRole: 'cheap' });
const premiumRoleCount = await User.countDocuments({ userRole: 'premium' });
const vipCount = await User.countDocuments({ userRole: 'vip' });
const supremeCount = await User.countDocuments({ userRole: 'supreme' });
let dbSize = '0 MB';
let storageSize = '0 GB';
try {
const dbStats = await mongoose.connection.db.stats();
dbSize = (dbStats.dataSize / 1024 / 1024).toFixed(2) + ' MB';
storageSize = (dbStats.storageSize / 1024 / 1024 / 1024).toFixed(2) + ' GB';
} catch (dbError) {
console.log('DB stats not available:', dbError.message);
}
const memUsage = process.memoryUsage();
const ramUsage = (memUsage.heapUsed / 1024 / 1024).toFixed(2) + ' MB';
const cpuUsage = process.cpuUsage();
const cpuPercent = ((cpuUsage.user + cpuUsage.system) / 1000000).toFixed(2);
res.json({
success: true,
stats: {
totalUsers,
regularUsers,
premiumUsers,
roleDistribution: {
regular: regularUsers,
cheap: cheapCount,
premium: premiumRoleCount,
vip: vipCount,
supreme: supremeCount
},
database: {
size: dbSize
},
system: {
ramUsage: ramUsage,
cpuUsage: cpuPercent,
storageUsed: storageSize
}
}
});
} catch (error) {
console.error('Server stats error:', error);
res.status(500).json({
success: false,
error: 'Internal server error',
details: error.message
});
}
});
app.post('/api/admin/set-role', authenticate, async (req, res) => {
try {
if (req.user.role !== 'admin') {
return res.status(403).json({ success: false, error: 'Admin access required' });
}
const { userId, roleName, customApiKey } = req.body;
if (!userId || !roleName) {
return res.status(400).json({ success: false, error: 'User ID and role name required' });
}
const user = await User.findById(userId);
if (!user) {
return res.status(404).json({ success: false, error: 'User not found' });
}
if (user.role === 'admin') {
return res.status(403).json({ success: false, error: 'Cannot modify admin users' });
}
const roleConfig = {
cheap: { limit: 500, premium: true },
premium: { limit: 1500, premium: true },
vip: { limit: 2500, premium: true },
supreme: { limit: 3000, premium: true }
};
if (!roleConfig[roleName]) {
return res.status(400).json({ success: false, error: 'Invalid role name' });
}
const expiresAt = new Date();
expiresAt.setMonth(expiresAt.getMonth() + 1);
let finalApiKey = user.apikey;
if (customApiKey && customApiKey.trim()) {
const existing = await User.findOne({ apikey: customApiKey });
if (existing && existing._id.toString() !== userId) {
return res.status(400).json({ success: false, error: 'API key already in use' });
}
user.apikey = customApiKey;
finalApiKey = customApiKey;
}
user.userRole = roleName;
user.userRoleExpiresAt = expiresAt;
user.limit = roleConfig[roleName].limit;
user.premium = roleConfig[roleName].premium;
user.premiumExpiredAt = expiresAt;
await user.save();
const userRole = await UserRole.findOne({ userId: user._id });
if (userRole) {
userRole.roleName = roleName;
userRole.customApiKey = customApiKey || null;
userRole.expiresAt = expiresAt;
userRole.createdBy = req.user.username;
await userRole.save();
} else {
await UserRole.create({
userId: user._id,
roleName,
customApiKey: customApiKey || null,
expiresAt,
createdBy: req.user.username
});
}
await logActivity(user._id, user.username, 'role_assigned', `Role ${roleName} assigned by admin`, {
roleName,
limit: user.limit,
expiresAt,
customApiKey: customApiKey || 'none',
assignedBy: req.user.username
});
res.json({
success: true,
message: `Role ${roleName} assigned successfully`,
expiresAt,
newLimit: user.limit,
apiKey: user.apikey
});
} catch (error) {
console.error('Set role error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.get('/api/admin/users', authenticate, async (req, res) => {
try {
if (req.user.role !== 'admin') {
return res.status(403).json({ success: false, error: 'Admin access required' });
}
const users = await User.find({}, {
password: 0
}).sort({ createdAt: -1 });
res.json({
success: true,
users: users.map(user => ({
id: user._id,
username: user.username,
email: user.email,
role: user.role,
userRole: user.userRole,
userRoleExpiresAt: user.userRoleExpiresAt,
premium: user.premium,
premiumExpiredAt: user.premiumExpiredAt,
banned: user.banned,
tempBanned: user.tempBanned,
tempBanUntil: user.tempBanUntil,
tempBanReason: user.tempBanReason,
limit: user.limit,
requests: user.requests,
requestsToday: user.requestsToday,
createdAt: user.createdAt,
ipAddress: user.ipAddress
}))
});
} catch (error) {
console.error('Admin users fetch error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.post('/api/admin/temp-ban', authenticate, async (req, res) => {
try {
if (req.user.role !== 'admin') {
return res.status(403).json({ success: false, error: 'Admin access required' });
}
const { userId, banUntil, reason } = req.body;
if (!userId || !banUntil) {
return res.status(400).json({
success: false,
error: 'User ID and ban until date are required'
});
}
const user = await User.findById(userId);
if (!user) {
return res.status(404).json({ success: false, error: 'User not found' });
}
if (user.role === 'admin') {
return res.status(403).json({ success: false, error: 'Cannot ban admin users' });
}
const banUntilDate = new Date(banUntil);
if (banUntilDate <= new Date()) {
return res.status(400).json({
success: false,
error: 'Ban until date must be in the future'
});
}
user.tempBanned = true;
user.tempBanUntil = banUntilDate;
user.tempBanReason = reason || 'No reason provided';
await user.save();
await logActivity(user._id, user.username, 'temp_banned', `User temporarily banned until ${banUntilDate.toLocaleString()}`, {
bannedBy: req.user.username,
banUntil: banUntilDate,
reason: user.tempBanReason
});
res.json({
success: true,
message: `User ${user.username} temporarily banned until ${banUntilDate.toLocaleString()}`
});
} catch (error) {
console.error('Temp ban error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.post('/api/admin/remove-temp-ban', authenticate, async (req, res) => {
try {
if (req.user.role !== 'admin') {
return res.status(403).json({ success: false, error: 'Admin access required' });
}
const { userId } = req.body;
if (!userId) {
return res.status(400).json({
success: false,
error: 'User ID is required'
});
}
const user = await User.findById(userId);
if (!user) {
return res.status(404).json({ success: false, error: 'User not found' });
}
user.tempBanned = false;
user.tempBanUntil = null;
user.tempBanReason = null;
await user.save();
await logActivity(user._id, user.username, 'ban_removed', 'Temporary ban removed by admin', {
removedBy: req.user.username
});
res.json({
success: true,
message: `Temporary ban removed for user ${user.username}`
});
} catch (error) {
console.error('Remove temp ban error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.post('/api/admin/redeem-code', authenticate, async (req, res) => {
try {
if (req.user.role !== 'admin') {
return res.status(403).json({ success: false, error: 'Admin access required' });
}
const { type, limitValue, codeExpired, premiumExpired } = req.body;
if (!type || !codeExpired) {
return res.status(400).json({
success: false,
error: 'Type and code expiration date are required'
});
}
const codeExpiredDate = new Date(codeExpired);
if (codeExpiredDate <= new Date()) {
return res.status(400).json({
success: false,
error: 'Code expiration date must be in the future'
});
}
if (type === 'limit' && (!limitValue || limitValue <= 0)) {
return res.status(400).json({
success: false,
error: 'Limit value must be greater than 0 for Limit Only type'
});
}
if (type === 'premium' && !premiumExpired) {
return res.status(400).json({
success: false,
error: 'Premium expiration date is required for Premium Only type'
});
}
if (type === 'both') {
if (!limitValue || limitValue <= 0) {
return res.status(400).json({
success: false,
error: 'Limit value must be greater than 0 for Both type'
});
}
if (!premiumExpired) {
return res.status(400).json({
success: false,
error: 'Premium expiration date is required for Both type'
});
}
}
let premiumExpiredDate = null;
if (premiumExpired) {
premiumExpiredDate = new Date(premiumExpired);
if (premiumExpiredDate <= new Date()) {
return res.status(400).json({
success: false,
error: 'Premium expiration date must be in the future'
});
}
}
const code = crypto.randomBytes(4).toString('hex').toUpperCase();
const redeemCode = new RedeemCode({
code,
type,
limitValue: parseInt(limitValue) || 0,
codeExpired: codeExpiredDate,
premiumExpired: premiumExpiredDate,
createdBy: req.user.username
});
await redeemCode.save();
await logActivity(req.user._id, req.user.username, 'redeem_code_created', `Created redeem code: ${code}`, {
code,
type,
limitValue,
codeExpired: codeExpiredDate,
premiumExpired: premiumExpiredDate
});
res.json({ success: true, code });
} catch (error) {
console.error('Redeem code creation error:', error);
res.status(500).json({ success: false, error: 'Internal server error' });
}
});
app.use('/api', checkBanned);
app.use('/api', apiRateLimit);
let pluginsDir = path.join(__dirname, "plugins");
let isJavaScriptFile = (fileName) => /\.js$/.test(fileName);
global.plugins = {};
const loadPlugins = () => {
if (!fs.existsSync(pluginsDir)) {
console.log('Plugins directory not found, creating...');
try {
fs.mkdirSync(pluginsDir, { recursive: true });
} catch (error) {
console.error('Error creating plugins directory:', error);
}
return;
}
for (let pluginFile of fs.readdirSync(pluginsDir).filter(isJavaScriptFile)) {
try {
delete require.cache[require.resolve(path.join(pluginsDir, pluginFile))];
global.plugins[pluginFile] = require(path.join(pluginsDir, pluginFile));
} catch (error) {
console.error(`Error loading plugin ${pluginFile}:`, error.message);
delete global.plugins[pluginFile];
}
}
console.log('Loaded plugins:', Object.keys(global.plugins));
};
global.reload = (event, filename) => {
if (/\.js$/.test(filename)) {
let fullFilePath = path.join(pluginsDir, filename);
if (fullFilePath in require.cache) {
delete require.cache[fullFilePath];
if (fs.existsSync(fullFilePath)) {
console.log(`♻️ Re-requiring plugin '${filename}'`);
} else {
console.log(`🗑️ Deleted plugin '${filename}'`);
return delete global.plugins[filename];
}
} else {
console.log(`🔁 Requiring new plugin '${filename}'`);
}
let errorCheck = syntaxError(fs.readFileSync(fullFilePath), filename);
if (errorCheck) {
console.error(`❌ Syntax error while loading '${filename}':\n${errorCheck}`);
} else {
try {
global.plugins[filename] = require(fullFilePath);
reloadHandler();
} catch (error) {
console.error(`Error loading plugin ${filename}:`, error);
} finally {
global.plugins = Object.fromEntries(Object.entries(global.plugins).sort(([a], [b]) => a.localeCompare(b)));
}
}
}
};
const reloadHandler = () => {
const routes = [];
Object.keys(global.plugins).forEach(file => {
const plugin = global.plugins[file];
if (plugin && plugin.enabled && plugin.routes && plugin.handler) {
plugin.routes.forEach(route => {
routes.push({ route, plugin, file });
});
}
});
routes.forEach(({ route, plugin, file }) => {
const method = (plugin.type || 'get').toLowerCase();
if (app[method] && typeof app[method] === 'function') {
app[method](`/${route}`, (req, res, next) => {
req.limitDeduction = plugin.limit || 1;
next();
}, validateApiKey, async (req, res) => {
const startTime = Date.now();
try {
await plugin.handler(req, res);
await RequestLog.create({
userId: req.apiUser._id,
username: req.apiUser.username,
apikey: req.apiUser.apikey,
endpoint: route,
ipAddress: req.realIP,
userAgent: req.get('User-Agent'),
success: true,
responseTime: Date.now() - startTime,
limitDeducted: req.limitDeducted || 1
});
} catch (error) {
console.error(`Plugin ${plugin.name} error:`, error);
await RequestLog.create({
userId: req.apiUser._id,
username: req.apiUser.username,
apikey: req.apiUser.apikey,
endpoint: route,
ipAddress: req.realIP,
userAgent: req.get('User-Agent'),
success: false,
responseTime: Date.now() - startTime,
limitDeducted: req.limitDeducted || 1
});
if (!res.headersSent) {
res.status(500).json({
success: false,
error: 'Plugin execution failed'
});
}
}
});
console.log(`✅ Registered route: ${method.toUpperCase()} /${route} from ${file}`);
}
});
};
Object.freeze(global.reload);
fs.watch(pluginsDir, global.reload);
setInterval(async () => {
const now = new Date();
if (now.getHours() === 0 && now.getMinutes() === 0) {
console.log('Running daily limit reset at midnight...');
try {
const users = await User.find({});
for (const user of users) {
await resetUserLimitIfNeeded(user);
}
console.log('Daily limit reset completed for all users');
} catch (error) {
console.error('Daily reset error:', error);
}
}
}, 60000);
initializeAdmin();
loadPlugins();
reloadHandler();
app.use('/', tmpRouter);
app.use((err, req, res, next) => {
console.error('Unhandled error:', err);
res.status(500).json({
success: false,
error: 'Internal server error'
});
});
const PORT = process.env.PORT || 7860;
app.listen(PORT, () => {
console.log(`DashX API Server running on port ${PORT}`);
console.log('=== ADMIN ACCOUNT INFO ===');
console.log('Username: HERXA');
console.log('Password: #HIDDEN#');
console.log('API Key: #HIDDEN#');
console.log('Limit: 9999');
console.log('=========================');
console.log('Database connected successfully');
console.log('Plugin auto-reload enabled');
console.log('Daily reset cron job started');
});