Trigger82 commited on
Commit
74fb878
Β·
verified Β·
1 Parent(s): dcc3a74

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +158 -80
server.js CHANGED
@@ -1,73 +1,102 @@
1
  const express = require('express');
2
- const { spawn } = require('child_process');
3
- const fs = require('fs');
4
  const path = require('path');
5
  const app = express();
6
  const http = require('http').createServer(app);
7
  const io = require('socket.io')(http);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  // Middleware
10
  app.use(express.static('public'));
11
  app.use(express.json());
12
 
13
- // User directories base path
14
- const USERS_DIR = path.join(__dirname, 'users');
15
-
16
- // Create users directory if it doesn't exist
17
- if (!fs.existsSync(USERS_DIR)) {
18
- fs.mkdirSync(USERS_DIR, { recursive: true });
19
- }
20
 
21
  // Socket.io connection handler
22
  io.on('connection', (socket) => {
23
- console.log('A user connected');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  // Handle repository cloning
26
- socket.on('cloneRepo', ({ userId, repoUrl }) => {
27
- const userDir = path.join(USERS_DIR, userId);
28
-
29
- // Create user directory if it doesn't exist
30
- if (!fs.existsSync(userDir)) {
31
- fs.mkdirSync(userDir, { recursive: true });
32
  }
33
 
34
- // Clone the repository
35
- const gitClone = spawn('git', ['clone', repoUrl, '.'], { cwd: userDir });
 
 
36
 
37
- gitClone.stdout.on('data', (data) => {
38
- socket.emit('output', data.toString());
39
- });
40
 
41
- gitClone.stderr.on('data', (data) => {
42
- socket.emit('output', data.toString());
43
- });
44
 
45
  gitClone.on('close', (code) => {
46
  if (code === 0) {
47
  socket.emit('output', 'βœ… Repository cloned successfully!');
48
- socket.emit('repoCloned', { success: true });
49
  } else {
50
  socket.emit('output', '❌ Failed to clone repository');
51
- socket.emit('repoCloned', { success: false });
52
  }
53
  });
54
  });
55
 
56
- // Handle npm/yarn install
57
- socket.on('installDeps', ({ userId, packageManager }) => {
58
- const userDir = path.join(USERS_DIR, userId);
59
- const command = packageManager === 'yarn' ? 'yarn' : 'npm';
60
- const args = ['install'];
61
-
62
- const installProcess = spawn(command, args, { cwd: userDir });
63
 
64
- installProcess.stdout.on('data', (data) => {
65
- socket.emit('output', data.toString());
66
- });
67
 
68
- installProcess.stderr.on('data', (data) => {
69
- socket.emit('output', data.toString());
70
- });
71
 
72
  installProcess.on('close', (code) => {
73
  if (code === 0) {
@@ -78,71 +107,120 @@ io.on('connection', (socket) => {
78
  });
79
  });
80
 
81
- // Handle starting the application
82
- socket.on('startApp', ({ userId, startCommand }) => {
83
- const userDir = path.join(USERS_DIR, userId);
84
- const [command, ...args] = startCommand.split(' ');
 
 
 
 
 
85
 
86
- const startProcess = spawn(command, args, { cwd: userDir });
 
 
 
87
 
88
- startProcess.stdout.on('data', (data) => {
89
- socket.emit('output', data.toString());
90
- });
91
 
92
- startProcess.stderr.on('data', (data) => {
93
- socket.emit('output', data.toString());
94
- });
95
 
96
- startProcess.on('close', (code) => {
97
- socket.emit('output', `Process exited with code ${code}`);
 
98
  });
99
-
100
- // Store the process reference so we can kill it later
101
- socket.process = startProcess;
102
  });
103
 
104
- // Handle stopping the application
105
- socket.on('stopApp', () => {
106
- if (socket.process) {
107
- socket.process.kill();
108
- socket.emit('output', 'πŸ›‘ Application stopped');
109
- } else {
110
- socket.emit('output', 'No running process to stop');
111
  }
 
 
 
 
 
 
 
 
 
 
 
112
  });
113
 
114
  // Handle file operations
115
- socket.on('readFile', ({ userId, filePath }) => {
116
- const fullPath = path.join(USERS_DIR, userId, filePath);
117
 
118
  fs.readFile(fullPath, 'utf8', (err, data) => {
119
- if (err) {
120
- socket.emit('output', `❌ Error reading file: ${err.message}`);
121
- } else {
122
- socket.emit('fileContent', { filePath, content: data });
123
- }
124
  });
125
  });
126
 
127
- socket.on('writeFile', ({ userId, filePath, content }) => {
128
- const fullPath = path.join(USERS_DIR, userId, filePath);
129
 
130
  fs.writeFile(fullPath, content, 'utf8', (err) => {
131
- if (err) {
132
- socket.emit('output', `❌ Error writing file: ${err.message}`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  } else {
134
- socket.emit('output', `βœ… File ${filePath} saved successfully`);
135
  }
136
- });
 
137
  });
138
 
 
139
  socket.on('disconnect', () => {
140
- console.log('User disconnected');
141
- if (socket.process) {
142
- socket.process.kill();
 
 
143
  }
144
  });
145
  });
146
 
147
- const PORT = process.env.PORT || 7860;
148
- http.listen(PORT, () => console.log(`🌐 Server running on port ${PORT}`));
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  const express = require('express');
2
+ const { spawn, exec } = require('child_process');
3
+ const fs = require('fs-extra');
4
  const path = require('path');
5
  const app = express();
6
  const http = require('http').createServer(app);
7
  const io = require('socket.io')(http);
8
+ const crypto = require('crypto');
9
+ const fetch = require('node-fetch');
10
+
11
+ // Configuration
12
+ const PORT = process.env.PORT || 7860;
13
+ const USERS_DIR = path.join(__dirname, 'users');
14
+ const SESSIONS_FILE = path.join(__dirname, 'sessions.json');
15
+ const BANNED_FILE = path.join(__dirname, 'banned.json');
16
+ const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || crypto.randomBytes(16).toString('hex');
17
+
18
+ // Ensure directories exist
19
+ fs.ensureDirSync(USERS_DIR);
20
+ if (!fs.existsSync(SESSIONS_FILE)) fs.writeFileSync(SESSIONS_FILE, '{}');
21
+ if (!fs.existsSync(BANNED_FILE)) fs.writeFileSync(BANNED_FILE, '[]');
22
+
23
+ // Store active processes
24
+ const activeProcesses = {};
25
 
26
  // Middleware
27
  app.use(express.static('public'));
28
  app.use(express.json());
29
 
30
+ // Load banned users
31
+ const loadBannedUsers = () => JSON.parse(fs.readFileSync(BANNED_FILE));
32
+ const isBanned = (ip) => loadBannedUsers().includes(ip);
 
 
 
 
33
 
34
  // Socket.io connection handler
35
  io.on('connection', (socket) => {
36
+ const clientIp = socket.handshake.address;
37
+ console.log(`New connection from ${clientIp}`);
38
+
39
+ // Check if banned
40
+ if (isBanned(clientIp)) {
41
+ socket.emit('output', '❌ You are banned from this service');
42
+ socket.disconnect(true);
43
+ return;
44
+ }
45
+
46
+ // Generate session ID
47
+ const sessionId = crypto.randomBytes(8).toString('hex');
48
+ const sessionDir = path.join(USERS_DIR, sessionId);
49
+
50
+ // Ensure session directory exists
51
+ fs.ensureDirSync(sessionDir);
52
+
53
+ // Store session info
54
+ const sessions = JSON.parse(fs.readFileSync(SESSIONS_FILE));
55
+ sessions[sessionId] = {
56
+ ip: clientIp,
57
+ createdAt: new Date().toISOString(),
58
+ lastActivity: new Date().toISOString()
59
+ };
60
+ fs.writeFileSync(SESSIONS_FILE, JSON.stringify(sessions, null, 2));
61
 
62
  // Handle repository cloning
63
+ socket.on('clone', (repoUrl) => {
64
+ if (!repoUrl.startsWith('https://github.com/')) {
65
+ return socket.emit('output', '❌ Invalid GitHub repository URL');
 
 
 
66
  }
67
 
68
+ socket.emit('output', `πŸ”„ Cloning ${repoUrl}...`);
69
+
70
+ // Clear directory first
71
+ fs.emptyDirSync(sessionDir);
72
 
73
+ const gitClone = spawn('git', ['clone', repoUrl, '.'], { cwd: sessionDir });
 
 
74
 
75
+ gitClone.stdout.on('data', (data) => socket.emit('output', data.toString()));
76
+ gitClone.stderr.on('data', (data) => socket.emit('output', data.toString()));
 
77
 
78
  gitClone.on('close', (code) => {
79
  if (code === 0) {
80
  socket.emit('output', 'βœ… Repository cloned successfully!');
81
+ socket.emit('clone-complete');
82
  } else {
83
  socket.emit('output', '❌ Failed to clone repository');
 
84
  }
85
  });
86
  });
87
 
88
+ // Handle dependency installation
89
+ socket.on('install', (packageManager) => {
90
+ if (!['npm', 'yarn'].includes(packageManager)) {
91
+ return socket.emit('output', '❌ Invalid package manager');
92
+ }
 
 
93
 
94
+ socket.emit('output', `πŸ“¦ Installing dependencies with ${packageManager}...`);
95
+
96
+ const installProcess = spawn(packageManager, ['install'], { cwd: sessionDir });
97
 
98
+ installProcess.stdout.on('data', (data) => socket.emit('output', data.toString()));
99
+ installProcess.stderr.on('data', (data) => socket.emit('output', data.toString()));
 
100
 
101
  installProcess.on('close', (code) => {
102
  if (code === 0) {
 
107
  });
108
  });
109
 
110
+ // Handle application start
111
+ socket.on('start', (command) => {
112
+ if (!command) return socket.emit('output', '❌ No command provided');
113
+
114
+ // Kill any existing process for this session
115
+ if (activeProcesses[sessionId]) {
116
+ activeProcesses[sessionId].kill();
117
+ delete activeProcesses[sessionId];
118
+ }
119
 
120
+ socket.emit('output', `πŸš€ Starting: ${command}`);
121
+
122
+ const [cmd, ...args] = command.split(' ');
123
+ const process = spawn(cmd, args, { cwd: sessionDir });
124
 
125
+ activeProcesses[sessionId] = process;
 
 
126
 
127
+ process.stdout.on('data', (data) => socket.emit('output', data.toString()));
128
+ process.stderr.on('data', (data) => socket.emit('output', data.toString()));
 
129
 
130
+ process.on('close', (code) => {
131
+ socket.emit('output', `πŸ”΄ Process exited with code ${code}`);
132
+ delete activeProcesses[sessionId];
133
  });
 
 
 
134
  });
135
 
136
+ // Handle PM2 commands
137
+ socket.on('pm2', (subcommand) => {
138
+ if (!['start', 'stop', 'restart', 'list', 'logs'].includes(subcommand)) {
139
+ return socket.emit('output', '❌ Invalid PM2 command');
 
 
 
140
  }
141
+
142
+ socket.emit('output', `⚑ Executing: pm2 ${subcommand}`);
143
+
144
+ const pm2Process = spawn('pm2', [subcommand], { cwd: sessionDir });
145
+
146
+ pm2Process.stdout.on('data', (data) => socket.emit('output', data.toString()));
147
+ pm2Process.stderr.on('data', (data) => socket.emit('output', data.toString()));
148
+
149
+ pm2Process.on('close', (code) => {
150
+ socket.emit('output', `PM2 ${subcommand} completed with code ${code}`);
151
+ });
152
  });
153
 
154
  // Handle file operations
155
+ socket.on('read-file', (filePath, callback) => {
156
+ const fullPath = path.join(sessionDir, filePath);
157
 
158
  fs.readFile(fullPath, 'utf8', (err, data) => {
159
+ if (err) return callback({ error: err.message });
160
+ callback({ content: data });
 
 
 
161
  });
162
  });
163
 
164
+ socket.on('write-file', ({ filePath, content }, callback) => {
165
+ const fullPath = path.join(sessionDir, filePath);
166
 
167
  fs.writeFile(fullPath, content, 'utf8', (err) => {
168
+ if (err) return callback({ error: err.message });
169
+ callback({ success: true });
170
+ });
171
+ });
172
+
173
+ // Handle directory listing
174
+ socket.on('list-files', (dirPath, callback) => {
175
+ const fullPath = path.join(sessionDir, dirPath || '');
176
+
177
+ fs.readdir(fullPath, (err, files) => {
178
+ if (err) return callback({ error: err.message });
179
+ callback({ files });
180
+ });
181
+ });
182
+
183
+ // Handle admin commands
184
+ socket.on('admin', ({ password, command }) => {
185
+ if (password !== ADMIN_PASSWORD) {
186
+ return socket.emit('output', '❌ Invalid admin password');
187
+ }
188
+
189
+ if (command === 'ban') {
190
+ const banned = loadBannedUsers();
191
+ if (!banned.includes(clientIp)) {
192
+ banned.push(clientIp);
193
+ fs.writeFileSync(BANNED_FILE, JSON.stringify(banned));
194
+ socket.emit('output', `βœ… Banned IP: ${clientIp}`);
195
  } else {
196
+ socket.emit('output', '⚠️ IP already banned');
197
  }
198
+ }
199
+ // Add more admin commands as needed
200
  });
201
 
202
+ // Handle disconnection
203
  socket.on('disconnect', () => {
204
+ console.log(`Client disconnected: ${clientIp}`);
205
+ // Clean up any active processes
206
+ if (activeProcesses[sessionId]) {
207
+ activeProcesses[sessionId].kill();
208
+ delete activeProcesses[sessionId];
209
  }
210
  });
211
  });
212
 
213
+ // Start the server
214
+ http.listen(PORT, () => {
215
+ console.log(`πŸš€ Server running on port ${PORT}`);
216
+ console.log(`πŸ”‘ Admin password: ${ADMIN_PASSWORD}`);
217
+ });
218
+
219
+ // Error handling
220
+ process.on('uncaughtException', (err) => {
221
+ console.error('Uncaught Exception:', err);
222
+ });
223
+
224
+ process.on('unhandledRejection', (reason, promise) => {
225
+ console.error('Unhandled Rejection at:', promise, 'reason:', reason);
226
+ });