itszubariel commited on
Commit
5fa0cf6
·
1 Parent(s): fc63c00

update to include a timer and also timeout reduced to 2hr from 4hr

Browse files
Files changed (2) hide show
  1. Dockerfile +4 -0
  2. src/server.ts +70 -149
Dockerfile CHANGED
@@ -1,6 +1,10 @@
1
  FROM node:20-slim
2
  RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
 
3
  ARG CACHEBUST=1780809050
 
 
 
4
  RUN curl -L https://github.com/zbrlang/zbr/releases/latest/download/zbr-linux-x64 -o /usr/local/bin/zbr && chmod +x /usr/local/bin/zbr
5
  WORKDIR /app
6
  COPY package*.json ./
 
1
  FROM node:20-slim
2
  RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
3
+ <<<<<<< HEAD
4
  ARG CACHEBUST=1780809050
5
+ =======
6
+ ARG CACHEBUST=67
7
+ >>>>>>> 31e0dec (update to include a timer and also timeout reduced to 2hr from 4hr)
8
  RUN curl -L https://github.com/zbrlang/zbr/releases/latest/download/zbr-linux-x64 -o /usr/local/bin/zbr && chmod +x /usr/local/bin/zbr
9
  WORKDIR /app
10
  COPY package*.json ./
src/server.ts CHANGED
@@ -1,189 +1,110 @@
1
  import express, { Request, Response, NextFunction } from 'express';
2
-
3
  import { spawn, execSync, ChildProcess } from 'child_process';
4
-
5
  import fs from 'fs';
6
-
7
  import path from 'path';
8
 
9
  interface BotProcess {
10
-
11
- child: ChildProcess;
12
-
13
- tempDir: string;
14
-
15
  }
16
-
17
  interface Command {
18
-
19
- filename: string;
20
-
21
- content: string;
22
-
23
  }
24
-
25
  interface RunRequestBody {
26
-
27
- botId: string;
28
-
29
- discordId: string;
30
-
31
- envFile: string;
32
-
33
- zbrJson: string;
34
-
35
- commands: Command[];
36
-
37
- dbBase64: string;
38
-
39
  }
40
-
41
  interface StopRequestBody {
42
-
43
- botId: string;
44
-
45
- discordId: string;
46
-
47
  }
48
 
49
  const app = express();
50
-
51
  app.use(express.json({ limit: '10mb' }));
52
-
53
  const ZBR_SECRET = process.env.ZBR_SECRET;
54
-
55
  const processes = new Map<string, BotProcess>();
56
 
57
  try {
58
-
59
- const version = execSync('/usr/local/bin/zbr --version').toString().trim();
60
-
61
- const size = execSync('wc -c < /usr/local/bin/zbr').toString().trim();
62
-
63
- console.log('ZBR binary version:', version, '| size:', size, 'bytes');
64
-
65
  } catch (e) {
66
-
67
- console.error("Failed to execute ZBR binary:", e);
68
-
69
  }
70
 
71
  const auth = (req: Request, res: Response, next: NextFunction): void | Response => {
72
-
73
- if (req.path === '/health') return next();
74
-
75
- if (req.headers['x-zbr-secret'] !== ZBR_SECRET) {
76
-
77
- return res.status(401).send('Unauthorized');
78
-
79
- }
80
-
81
- next();
82
-
83
  };
84
-
85
  app.use(auth);
86
 
87
  app.post('/run', (req: Request<{}, any, RunRequestBody>, res: Response) => {
88
-
89
- const { botId, discordId, envFile, zbrJson, commands, dbBase64 } = req.body;
90
-
91
- const key = `${discordId}-${botId}`;
92
-
93
- if (processes.has(key)) return res.status(400).send('Bot already running');
94
-
95
- const tempDir = `/tmp/zbr-${discordId}-${botId}`;
96
-
97
- fs.mkdirSync(tempDir, { recursive: true });
98
-
99
- fs.writeFileSync(path.join(tempDir, '.env'), envFile);
100
-
101
- fs.writeFileSync(path.join(tempDir, 'zbr.json'), zbrJson);
102
-
103
- const commandsDir = path.join(tempDir, 'commands');
104
-
105
- fs.mkdirSync(commandsDir, { recursive: true });
106
-
107
- commands.forEach(cmd => {
108
-
109
- fs.writeFileSync(path.join(commandsDir, cmd.filename), cmd.content);
110
-
111
- });
112
-
113
- fs.writeFileSync(path.join(tempDir, 'zbr.db'), Buffer.from(dbBase64, 'base64'));
114
-
115
- const child = spawn('/usr/local/bin/zbr', [], {
116
-
117
- cwd: tempDir,
118
-
119
- stdio: ['ignore', 'pipe', 'pipe']
120
-
121
- });
122
-
123
- if (child.stdout) {
124
-
125
- child.stdout.on('data', (data) => console.log(data.toString()));
126
-
127
- }
128
-
129
- if (child.stderr) {
130
-
131
- child.stderr.on('data', (data) => console.error(data.toString()));
132
-
133
- }
134
-
135
- processes.set(key, { child, tempDir });
136
-
137
- setTimeout(() => {
138
-
139
- if (processes.has(key)) stopBot(key);
140
-
141
- }, 4 * 60 * 60 * 1000); // make this 1 hour in the next update
142
-
143
- res.json({ success: true, status: 'running' });
144
-
145
  });
146
 
147
  function stopBot(key: string): boolean {
148
-
149
- const proc = processes.get(key);
150
-
151
- if (!proc) return false;
152
-
153
- proc.child.kill();
154
-
155
- fs.rmSync(proc.tempDir, { recursive: true, force: true });
156
-
157
- processes.delete(key);
158
-
159
- return true;
160
-
161
  }
162
 
163
  app.post('/stop', (req: Request<{}, any, StopRequestBody>, res: Response) => {
164
-
165
- const { botId, discordId } = req.body;
166
-
167
- if (stopBot(`${discordId}-${botId}`)) {
168
-
169
- res.json({ success: true, status: 'stopped' });
170
-
171
- } else {
172
-
173
- res.status(404).send('Bot not running');
174
-
175
- }
176
-
177
  });
178
 
179
  app.get('/status/:discordId/:botId', (req: Request, res: Response) => {
180
-
181
- const { discordId, botId } = req.params;
182
-
183
- res.json({ status: processes.has(`${discordId}-${botId}`) ? 'running' : 'stopped' });
184
-
 
 
185
  });
186
 
187
  app.get('/health', (req: Request, res: Response) => res.json({ ok: true }));
188
-
189
- app.listen(7860, () => console.log('Server running on port 7860'));
 
1
  import express, { Request, Response, NextFunction } from 'express';
 
2
  import { spawn, execSync, ChildProcess } from 'child_process';
 
3
  import fs from 'fs';
 
4
  import path from 'path';
5
 
6
  interface BotProcess {
7
+ child: ChildProcess;
8
+ tempDir: string;
9
+ startedAt: number;
 
 
10
  }
 
11
  interface Command {
12
+ filename: string;
13
+ content: string;
 
 
 
14
  }
 
15
  interface RunRequestBody {
16
+ botId: string;
17
+ discordId: string;
18
+ envFile: string;
19
+ zbrJson: string;
20
+ commands: Command[];
21
+ dbBase64: string;
 
 
 
 
 
 
 
22
  }
 
23
  interface StopRequestBody {
24
+ botId: string;
25
+ discordId: string;
 
 
 
26
  }
27
 
28
  const app = express();
 
29
  app.use(express.json({ limit: '10mb' }));
 
30
  const ZBR_SECRET = process.env.ZBR_SECRET;
 
31
  const processes = new Map<string, BotProcess>();
32
 
33
  try {
34
+ const version = execSync('/usr/local/bin/zbr --version').toString().trim();
35
+ const size = execSync('wc -c < /usr/local/bin/zbr').toString().trim();
36
+ console.log('ZBR binary version:', version, '| size:', size, 'bytes');
 
 
 
 
37
  } catch (e) {
38
+ console.error("Failed to execute ZBR binary:", e);
 
 
39
  }
40
 
41
  const auth = (req: Request, res: Response, next: NextFunction): void | Response => {
42
+ if (req.path === '/health') return next();
43
+ if (req.headers['x-zbr-secret'] !== ZBR_SECRET) {
44
+ return res.status(401).send('Unauthorized');
45
+ }
46
+ next();
 
 
 
 
 
 
47
  };
 
48
  app.use(auth);
49
 
50
  app.post('/run', (req: Request<{}, any, RunRequestBody>, res: Response) => {
51
+ const { botId, discordId, envFile, zbrJson, commands, dbBase64 } = req.body;
52
+ const key = `${discordId}-${botId}`;
53
+ if (processes.has(key)) return res.status(400).send('Bot already running');
54
+ const tempDir = `/tmp/zbr-${discordId}-${botId}`;
55
+ fs.mkdirSync(tempDir, { recursive: true });
56
+ fs.writeFileSync(path.join(tempDir, '.env'), envFile);
57
+ fs.writeFileSync(path.join(tempDir, 'zbr.json'), zbrJson);
58
+ const commandsDir = path.join(tempDir, 'commands');
59
+ fs.mkdirSync(commandsDir, { recursive: true });
60
+ commands.forEach(cmd => {
61
+ fs.writeFileSync(path.join(commandsDir, cmd.filename), cmd.content);
62
+ });
63
+ fs.writeFileSync(path.join(tempDir, 'zbr.db'), Buffer.from(dbBase64, 'base64'));
64
+ const child = spawn('/usr/local/bin/zbr', [], {
65
+ cwd: tempDir,
66
+ stdio: ['ignore', 'pipe', 'pipe']
67
+ });
68
+ if (child.stdout) {
69
+ child.stdout.on('data', (data) => console.log(data.toString()));
70
+ }
71
+ if (child.stderr) {
72
+ child.stderr.on('data', (data) => console.error(data.toString()));
73
+ }
74
+ processes.set(key, { child, tempDir, startedAt: Date.now() });
75
+ setTimeout(() => {
76
+ if (processes.has(key)) stopBot(key);
77
+ }, 2 * 60 * 60 * 1000);
78
+ res.json({ success: true, status: 'running' });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  });
80
 
81
  function stopBot(key: string): boolean {
82
+ const proc = processes.get(key);
83
+ if (!proc) return false;
84
+ proc.child.kill();
85
+ fs.rmSync(proc.tempDir, { recursive: true, force: true });
86
+ processes.delete(key);
87
+ return true;
 
 
 
 
 
 
 
88
  }
89
 
90
  app.post('/stop', (req: Request<{}, any, StopRequestBody>, res: Response) => {
91
+ const { botId, discordId } = req.body;
92
+ if (stopBot(`${discordId}-${botId}`)) {
93
+ res.json({ success: true, status: 'stopped' });
94
+ } else {
95
+ res.status(404).send('Bot not running');
96
+ }
 
 
 
 
 
 
 
97
  });
98
 
99
  app.get('/status/:discordId/:botId', (req: Request, res: Response) => {
100
+ const { discordId, botId } = req.params;
101
+ const proc = processes.get(`${discordId}-${botId}`);
102
+ if (proc) {
103
+ res.json({ status: 'running', startedAt: proc.startedAt });
104
+ } else {
105
+ res.json({ status: 'stopped' });
106
+ }
107
  });
108
 
109
  app.get('/health', (req: Request, res: Response) => res.json({ ok: true }));
110
+ app.listen(7860, () => console.log('Server running on port 7860'));