Try / server.js
Trigger82's picture
Update server.js
4d87935 verified
raw
history blame
7.69 kB
const fs = require('fs-extra');
const path = require('path');
// Configure directories
const USERS_DIR = path.join(__dirname, 'users');
// Ensure directories exist with proper permissions
try {
fs.ensureDirSync(USERS_DIR);
console.log('βœ… Users directory ready');
} catch (err) {
console.error('❌ Failed to setup users directory:', err);
process.exit(1);
}
// Rest of your server code remains the same...
const express = require('express');
const { spawn, exec } = require('child_process');
const fs = require('fs-extra');
const path = require('path');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
const crypto = require('crypto');
const fetch = require('node-fetch');
// Configuration
const PORT = process.env.PORT || 7860;
const USERS_DIR = path.join(__dirname, 'users');
const SESSIONS_FILE = path.join(__dirname, 'sessions.json');
const BANNED_FILE = path.join(__dirname, 'banned.json');
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || crypto.randomBytes(16).toString('hex');
// Ensure directories exist
fs.ensureDirSync(USERS_DIR);
if (!fs.existsSync(SESSIONS_FILE)) fs.writeFileSync(SESSIONS_FILE, '{}');
if (!fs.existsSync(BANNED_FILE)) fs.writeFileSync(BANNED_FILE, '[]');
// Store active processes
const activeProcesses = {};
// Middleware
app.use(express.static('public'));
app.use(express.json());
// Load banned users
const loadBannedUsers = () => JSON.parse(fs.readFileSync(BANNED_FILE));
const isBanned = (ip) => loadBannedUsers().includes(ip);
// Socket.io connection handler
io.on('connection', (socket) => {
const clientIp = socket.handshake.address;
console.log(`New connection from ${clientIp}`);
// Check if banned
if (isBanned(clientIp)) {
socket.emit('output', '❌ You are banned from this service');
socket.disconnect(true);
return;
}
// Generate session ID
const sessionId = crypto.randomBytes(8).toString('hex');
const sessionDir = path.join(USERS_DIR, sessionId);
// Ensure session directory exists
fs.ensureDirSync(sessionDir);
// Store session info
const sessions = JSON.parse(fs.readFileSync(SESSIONS_FILE));
sessions[sessionId] = {
ip: clientIp,
createdAt: new Date().toISOString(),
lastActivity: new Date().toISOString()
};
fs.writeFileSync(SESSIONS_FILE, JSON.stringify(sessions, null, 2));
// Handle repository cloning
socket.on('clone', (repoUrl) => {
if (!repoUrl.startsWith('https://github.com/')) {
return socket.emit('output', '❌ Invalid GitHub repository URL');
}
socket.emit('output', `πŸ”„ Cloning ${repoUrl}...`);
// Clear directory first
fs.emptyDirSync(sessionDir);
const gitClone = spawn('git', ['clone', repoUrl, '.'], { cwd: sessionDir });
gitClone.stdout.on('data', (data) => socket.emit('output', data.toString()));
gitClone.stderr.on('data', (data) => socket.emit('output', data.toString()));
gitClone.on('close', (code) => {
if (code === 0) {
socket.emit('output', 'βœ… Repository cloned successfully!');
socket.emit('clone-complete');
} else {
socket.emit('output', '❌ Failed to clone repository');
}
});
});
// Handle dependency installation
socket.on('install', (packageManager) => {
if (!['npm', 'yarn'].includes(packageManager)) {
return socket.emit('output', '❌ Invalid package manager');
}
socket.emit('output', `πŸ“¦ Installing dependencies with ${packageManager}...`);
const installProcess = spawn(packageManager, ['install'], { cwd: sessionDir });
installProcess.stdout.on('data', (data) => socket.emit('output', data.toString()));
installProcess.stderr.on('data', (data) => socket.emit('output', data.toString()));
installProcess.on('close', (code) => {
if (code === 0) {
socket.emit('output', 'βœ… Dependencies installed successfully!');
} else {
socket.emit('output', '❌ Failed to install dependencies');
}
});
});
// Handle application start
socket.on('start', (command) => {
if (!command) return socket.emit('output', '❌ No command provided');
// Kill any existing process for this session
if (activeProcesses[sessionId]) {
activeProcesses[sessionId].kill();
delete activeProcesses[sessionId];
}
socket.emit('output', `πŸš€ Starting: ${command}`);
const [cmd, ...args] = command.split(' ');
const process = spawn(cmd, args, { cwd: sessionDir });
activeProcesses[sessionId] = process;
process.stdout.on('data', (data) => socket.emit('output', data.toString()));
process.stderr.on('data', (data) => socket.emit('output', data.toString()));
process.on('close', (code) => {
socket.emit('output', `πŸ”΄ Process exited with code ${code}`);
delete activeProcesses[sessionId];
});
});
// Handle PM2 commands
socket.on('pm2', (subcommand) => {
if (!['start', 'stop', 'restart', 'list', 'logs'].includes(subcommand)) {
return socket.emit('output', '❌ Invalid PM2 command');
}
socket.emit('output', `⚑ Executing: pm2 ${subcommand}`);
const pm2Process = spawn('pm2', [subcommand], { cwd: sessionDir });
pm2Process.stdout.on('data', (data) => socket.emit('output', data.toString()));
pm2Process.stderr.on('data', (data) => socket.emit('output', data.toString()));
pm2Process.on('close', (code) => {
socket.emit('output', `PM2 ${subcommand} completed with code ${code}`);
});
});
// Handle file operations
socket.on('read-file', (filePath, callback) => {
const fullPath = path.join(sessionDir, filePath);
fs.readFile(fullPath, 'utf8', (err, data) => {
if (err) return callback({ error: err.message });
callback({ content: data });
});
});
socket.on('write-file', ({ filePath, content }, callback) => {
const fullPath = path.join(sessionDir, filePath);
fs.writeFile(fullPath, content, 'utf8', (err) => {
if (err) return callback({ error: err.message });
callback({ success: true });
});
});
// Handle directory listing
socket.on('list-files', (dirPath, callback) => {
const fullPath = path.join(sessionDir, dirPath || '');
fs.readdir(fullPath, (err, files) => {
if (err) return callback({ error: err.message });
callback({ files });
});
});
// Handle admin commands
socket.on('admin', ({ password, command }) => {
if (password !== ADMIN_PASSWORD) {
return socket.emit('output', '❌ Invalid admin password');
}
if (command === 'ban') {
const banned = loadBannedUsers();
if (!banned.includes(clientIp)) {
banned.push(clientIp);
fs.writeFileSync(BANNED_FILE, JSON.stringify(banned));
socket.emit('output', `βœ… Banned IP: ${clientIp}`);
} else {
socket.emit('output', '⚠️ IP already banned');
}
}
// Add more admin commands as needed
});
// Handle disconnection
socket.on('disconnect', () => {
console.log(`Client disconnected: ${clientIp}`);
// Clean up any active processes
if (activeProcesses[sessionId]) {
activeProcesses[sessionId].kill();
delete activeProcesses[sessionId];
}
});
});
// Start the server
http.listen(PORT, () => {
console.log(`πŸš€ Server running on port ${PORT}`);
console.log(`πŸ”‘ Admin password: ${ADMIN_PASSWORD}`);
});
// Error handling
process.on('uncaughtException', (err) => {
console.error('Uncaught Exception:', err);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});