Trigger82 commited on
Commit
bbf51df
Β·
verified Β·
1 Parent(s): 0224d1a

Create server.js

Browse files
Files changed (1) hide show
  1. server.js +205 -0
server.js ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require('express');
2
+ const { spawn } = require('child_process');
3
+ const { MongoClient } = require('mongodb');
4
+ const path = require('path');
5
+ const app = express();
6
+ const http = require('http').createServer(app);
7
+ const io = require('socket.io')(http, {
8
+ cors: {
9
+ origin: "*",
10
+ methods: ["GET", "POST"]
11
+ }
12
+ });
13
+ const crypto = require('crypto');
14
+ const fetch = require('node-fetch');
15
+
16
+ // Connect to MongoDB
17
+ const MONGO_URI = process.env.MONGO_URI || "mongodb://localhost:27017";
18
+ let db;
19
+
20
+ async function connectDB() {
21
+ try {
22
+ const client = new MongoClient(MONGO_URI);
23
+ await client.connect();
24
+ db = client.db('whatsapp-bots');
25
+ console.log("βœ… Connected to MongoDB");
26
+
27
+ // Create collections if they don't exist
28
+ const collections = ['users', 'bots', 'settings'];
29
+ for (const colName of collections) {
30
+ if (!(await db.listCollections({name: colName}).hasNext())) {
31
+ await db.createCollection(colName);
32
+ console.log(`Created collection: ${colName}`);
33
+ }
34
+ }
35
+
36
+ // Create admin user if not exists
37
+ const adminExists = await db.collection('users').findOne({username: 'admin'});
38
+ if (!adminExists) {
39
+ await db.collection('users').insertOne({
40
+ username: 'admin',
41
+ password: crypto.createHash('sha256').update('admin123').digest('hex'),
42
+ isAdmin: true,
43
+ createdAt: new Date()
44
+ });
45
+ console.log("πŸ‘‘ Created admin user (password: admin123)");
46
+ }
47
+
48
+ // Restart all bots that were running
49
+ const runningBots = await db.collection('bots').find({status: 'running'}).toArray();
50
+ runningBots.forEach(bot => {
51
+ startBotProcess(bot.userId, bot.repoUrl, bot.entryFile);
52
+ });
53
+ } catch (err) {
54
+ console.error("❌ MongoDB connection error:", err);
55
+ }
56
+ }
57
+
58
+ // Start a bot process
59
+ function startBotProcess(userId, repoUrl, entryFile) {
60
+ const botDir = `/persistent/storage/${userId}`;
61
+
62
+ // Clone repo if not exists
63
+ if (!require('fs').existsSync(botDir)) {
64
+ const clone = spawn('git', ['clone', repoUrl, botDir]);
65
+ clone.on('close', (code) => {
66
+ if (code === 0) {
67
+ console.log(`βœ… Cloned ${repoUrl} for user ${userId}`);
68
+ installDependencies(botDir, userId, repoUrl, entryFile);
69
+ } else {
70
+ console.error(`❌ Failed to clone ${repoUrl} for user ${userId}`);
71
+ }
72
+ });
73
+ } else {
74
+ installDependencies(botDir, userId, repoUrl, entryFile);
75
+ }
76
+ }
77
+
78
+ function installDependencies(botDir, userId, repoUrl, entryFile) {
79
+ const install = spawn('npm', ['install'], { cwd: botDir });
80
+ install.on('close', (code) => {
81
+ if (code === 0) {
82
+ console.log(`βœ… Installed dependencies for ${userId}`);
83
+ runBot(botDir, userId, repoUrl, entryFile);
84
+ } else {
85
+ console.error(`❌ Failed to install dependencies for ${userId}`);
86
+ }
87
+ });
88
+ }
89
+
90
+ function runBot(botDir, userId, repoUrl, entryFile) {
91
+ const botProcess = spawn('node', [entryFile], {
92
+ cwd: botDir,
93
+ stdio: ['pipe', 'pipe', 'pipe', 'ipc']
94
+ });
95
+
96
+ // Save to database
97
+ db.collection('bots').updateOne(
98
+ { userId },
99
+ { $set: {
100
+ status: 'running',
101
+ repoUrl,
102
+ entryFile,
103
+ startedAt: new Date(),
104
+ pid: botProcess.pid
105
+ }},
106
+ { upsert: true }
107
+ );
108
+
109
+ botProcess.stdout.on('data', (data) => {
110
+ io.to(userId).emit('bot-output', data.toString());
111
+ });
112
+
113
+ botProcess.stderr.on('data', (data) => {
114
+ io.to(userId).emit('bot-error', data.toString());
115
+ });
116
+
117
+ botProcess.on('close', (code) => {
118
+ console.log(`Bot ${userId} exited with code ${code}`);
119
+ db.collection('bots').updateOne(
120
+ { userId },
121
+ { $set: { status: 'stopped', exitCode: code } }
122
+ );
123
+ });
124
+ }
125
+
126
+ // Web server setup
127
+ app.use(express.static('public'));
128
+ app.use(express.json());
129
+
130
+ // API endpoints
131
+ app.post('/api/deploy', async (req, res) => {
132
+ const { userId, repoUrl, entryFile } = req.body;
133
+
134
+ if (!userId || !repoUrl || !entryFile) {
135
+ return res.status(400).json({ error: "Missing parameters" });
136
+ }
137
+
138
+ try {
139
+ startBotProcess(userId, repoUrl, entryFile);
140
+ res.json({ success: true, message: "Bot deployment started" });
141
+ } catch (err) {
142
+ res.status(500).json({ error: err.message });
143
+ }
144
+ });
145
+
146
+ // Socket.IO
147
+ io.on('connection', (socket) => {
148
+ console.log(`User connected: ${socket.id}`);
149
+
150
+ socket.on('register', async (data) => {
151
+ const { username, password } = data;
152
+ const hashedPassword = crypto.createHash('sha256').update(password).digest('hex');
153
+
154
+ try {
155
+ await db.collection('users').insertOne({
156
+ username,
157
+ password: hashedPassword,
158
+ createdAt: new Date()
159
+ });
160
+ socket.emit('register-success');
161
+ } catch (err) {
162
+ socket.emit('register-error', 'Username already exists');
163
+ }
164
+ });
165
+
166
+ socket.on('login', async (data) => {
167
+ const { username, password } = data;
168
+ const hashedPassword = crypto.createHash('sha256').update(password).digest('hex');
169
+
170
+ const user = await db.collection('users').findOne({
171
+ username,
172
+ password: hashedPassword
173
+ });
174
+
175
+ if (user) {
176
+ socket.emit('login-success', { userId: user._id.toString(), isAdmin: user.isAdmin });
177
+ socket.join(user._id.toString());
178
+ } else {
179
+ socket.emit('login-error', 'Invalid credentials');
180
+ }
181
+ });
182
+
183
+ socket.on('deploy-bot', (data) => {
184
+ const { userId, repoUrl, entryFile } = data;
185
+ startBotProcess(userId, repoUrl, entryFile);
186
+ });
187
+ });
188
+
189
+ // Start server
190
+ const PORT = process.env.PORT || 7860;
191
+ connectDB().then(() => {
192
+ http.listen(PORT, () => {
193
+ console.log(`πŸš€ Server running on port ${PORT}`);
194
+ console.log(`🌐 Open: http://localhost:${PORT}`);
195
+ });
196
+ });
197
+
198
+ // Error handling
199
+ process.on('uncaughtException', (err) => {
200
+ console.error('Uncaught Exception:', err);
201
+ });
202
+
203
+ process.on('unhandledRejection', (reason, promise) => {
204
+ console.error('Unhandled Rejection at:', promise, 'reason:', reason);
205
+ });