itszubariel commited on
Commit
563b757
·
1 Parent(s): 0b02bab

convert server to typescript

Browse files
Files changed (4) hide show
  1. Dockerfile +3 -3
  2. package.json +10 -2
  3. server.js → src/server.ts +60 -56
  4. tsconfig.json +13 -0
Dockerfile CHANGED
@@ -1,10 +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=3
4
- RUN curl -L https://github.com/zbrlang/zbr/raw/debug-binary/debug-zbr -o /usr/local/bin/zbr && chmod +x /usr/local/bin/zbr
5
  WORKDIR /app
6
  COPY package*.json ./
7
  RUN npm install
8
  COPY . .
 
9
  EXPOSE 7860
10
- CMD ["npm", "start"]
 
1
  FROM node:20-slim
2
  RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
3
+ RUN curl -L https://github.com/zbrlang/zbr/releases/latest/download/zbr -o /usr/local/bin/zbr && chmod +x /usr/local/bin/zbr
 
4
  WORKDIR /app
5
  COPY package*.json ./
6
  RUN npm install
7
  COPY . .
8
+ RUN npm run build
9
  EXPOSE 7860
10
+ CMD ["node", "dist/server.js"]
package.json CHANGED
@@ -2,17 +2,25 @@
2
  "name": "zbr-server",
3
  "version": "1.0.0",
4
  "description": "",
5
- "main": "server.js",
6
  "scripts": {
7
  "test": "echo \"Error: no test specified\" && exit 1",
8
- "start": "node server.js"
 
 
9
  },
10
  "keywords": [],
11
  "author": "",
12
  "license": "ISC",
13
  "type": "commonjs",
14
  "dependencies": {
 
 
15
  "express": "^4.21.0",
 
16
  "ws": "^8.21.0"
 
 
 
17
  }
18
  }
 
2
  "name": "zbr-server",
3
  "version": "1.0.0",
4
  "description": "",
5
+ "main": "dist/server.js",
6
  "scripts": {
7
  "test": "echo \"Error: no test specified\" && exit 1",
8
+ "start": "node dist/server.js",
9
+ "build": "tsc",
10
+ "dev": "ts-node src/server.ts"
11
  },
12
  "keywords": [],
13
  "author": "",
14
  "license": "ISC",
15
  "type": "commonjs",
16
  "dependencies": {
17
+ "@types/express": "^4.17.21",
18
+ "@types/node": "^20.12.7",
19
  "express": "^4.21.0",
20
+ "typescript": "^5.4.5",
21
  "ws": "^8.21.0"
22
+ },
23
+ "devDependencies": {
24
+ "ts-node": "^10.9.2"
25
  }
26
  }
server.js → src/server.ts RENAMED
@@ -1,20 +1,37 @@
1
- const express = require('express');
2
- const { spawn, execSync } = require('child_process');
3
- const fs = require('fs');
4
- const path = require('path');
5
- const WebSocket = require('ws');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  const app = express();
8
  app.use(express.json({ limit: '10mb' }));
9
 
10
  const ZBR_SECRET = process.env.ZBR_SECRET;
11
- const processes = new Map();
12
-
13
- // Discord Gateway Connectivity Test
14
- const ws = new WebSocket('wss://gateway.discord.gg/?v=10&encoding=json');
15
- ws.on('open', () => console.log('Discord WebSocket: REACHABLE'));
16
- ws.on('error', (e) => console.log('Discord WebSocket: BLOCKED -', e.message));
17
- ws.on('close', () => console.log('Discord WebSocket: closed'));
18
 
19
  try {
20
  const version = execSync('/usr/local/bin/zbr --version').toString();
@@ -23,62 +40,46 @@ try {
23
  console.error("Failed to execute ZBR binary:", e);
24
  }
25
 
26
- const auth = (req, res, next) => {
27
  if (req.path === '/health') return next();
28
- if (req.headers['x-zbr-secret'] !== ZBR_SECRET) return res.status(401).send('Unauthorized');
 
 
29
  next();
30
  };
31
 
32
  app.use(auth);
33
 
34
- app.post('/run', (req, res) => {
35
- console.log("Received payload keys:", Object.keys(req.body));
36
- console.log("Commands received:", req.body.commands?.length);
37
- console.log("Full .env received:", req.body.envFile);
38
-
39
  const { botId, discordId, envFile, zbrJson, commands, dbBase64 } = req.body;
40
  const key = `${discordId}-${botId}`;
41
  if (processes.has(key)) return res.status(400).send('Bot already running');
42
 
43
  const tempDir = `/tmp/zbr-${discordId}-${botId}`;
44
  fs.mkdirSync(tempDir, { recursive: true });
45
-
46
- const envPath = path.join(tempDir, '.env');
47
- fs.writeFileSync(envPath, envFile);
48
- console.log("Wrote .env to:", envPath, "Size:", fs.statSync(envPath).size);
49
-
50
- const jsonPath = path.join(tempDir, 'zbr.json');
51
- fs.writeFileSync(jsonPath, zbrJson);
52
- console.log("Wrote zbr.json to:", jsonPath, "Size:", fs.statSync(jsonPath).size);
53
-
54
  const commandsDir = path.join(tempDir, 'commands');
55
  fs.mkdirSync(commandsDir, { recursive: true });
56
  commands.forEach(cmd => {
57
- const cmdPath = path.join(commandsDir, cmd.filename);
58
- fs.writeFileSync(cmdPath, cmd.content);
59
- console.log("Wrote command to:", cmdPath, "Size:", fs.statSync(cmdPath).size);
60
- console.log("Content of", cmd.filename, ":", cmd.content);
61
- });
62
-
63
- const dbPath = path.join(tempDir, 'zbr.db');
64
- fs.writeFileSync(dbPath, Buffer.from(dbBase64, 'base64'));
65
- console.log("Wrote zbr.db to:", dbPath, "Size:", fs.statSync(dbPath).size);
66
-
67
- console.log("Directory listing", tempDir, ":", fs.readdirSync(tempDir));
68
- console.log("Directory listing", commandsDir, ":", fs.readdirSync(commandsDir));
69
-
70
- const spawnCmd = '/usr/local/bin/zbr';
71
- console.log("Spawning process:", spawnCmd, "in", tempDir);
72
- const child = spawn(spawnCmd, [], {
73
- cwd: tempDir,
74
- stdio: ['ignore', 'pipe', 'pipe']
75
  });
76
 
77
- const logWithTime = (msg, data) => console.log(`[${new Date().toISOString()}] [${key}] ${msg}`, data);
 
 
 
 
 
78
 
79
- child.stdout.on('data', (data) => logWithTime('stdout:', data.toString()));
80
- child.stderr.on('data', (data) => logWithTime('stderr:', data.toString()));
81
- child.on('exit', (code) => logWithTime('exited with code:', code));
 
 
 
82
 
83
  processes.set(key, { child, tempDir });
84
 
@@ -89,7 +90,7 @@ app.post('/run', (req, res) => {
89
  res.json({ success: true, status: 'running' });
90
  });
91
 
92
- function stopBot(key) {
93
  const proc = processes.get(key);
94
  if (!proc) return false;
95
  proc.child.kill();
@@ -98,17 +99,20 @@ function stopBot(key) {
98
  return true;
99
  }
100
 
101
- app.post('/stop', (req, res) => {
102
  const { botId, discordId } = req.body;
103
- if (stopBot(`${discordId}-${botId}`)) res.json({ success: true, status: 'stopped' });
104
- else res.status(404).send('Bot not running');
 
 
 
105
  });
106
 
107
- app.get('/status/:discordId/:botId', (req, res) => {
108
  const { discordId, botId } = req.params;
109
  res.json({ status: processes.has(`${discordId}-${botId}`) ? 'running' : 'stopped' });
110
  });
111
 
112
- app.get('/health', (req, res) => res.json({ ok: true }));
113
 
114
  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
+ }
10
+
11
+ interface Command {
12
+ filename: string;
13
+ content: string;
14
+ }
15
+
16
+ interface RunRequestBody {
17
+ botId: string;
18
+ discordId: string;
19
+ envFile: string;
20
+ zbrJson: string;
21
+ commands: Command[];
22
+ dbBase64: string;
23
+ }
24
+
25
+ interface StopRequestBody {
26
+ botId: string;
27
+ discordId: string;
28
+ }
29
 
30
  const app = express();
31
  app.use(express.json({ limit: '10mb' }));
32
 
33
  const ZBR_SECRET = process.env.ZBR_SECRET;
34
+ const processes = new Map<string, BotProcess>();
 
 
 
 
 
 
35
 
36
  try {
37
  const version = execSync('/usr/local/bin/zbr --version').toString();
 
40
  console.error("Failed to execute ZBR binary:", e);
41
  }
42
 
43
+ const auth = (req: Request, res: Response, next: NextFunction): void | Response => {
44
  if (req.path === '/health') return next();
45
+ if (req.headers['x-zbr-secret'] !== ZBR_SECRET) {
46
+ return res.status(401).send('Unauthorized');
47
+ }
48
  next();
49
  };
50
 
51
  app.use(auth);
52
 
53
+ app.post('/run', (req: Request<{}, any, RunRequestBody>, res: Response) => {
 
 
 
 
54
  const { botId, discordId, envFile, zbrJson, commands, dbBase64 } = req.body;
55
  const key = `${discordId}-${botId}`;
56
  if (processes.has(key)) return res.status(400).send('Bot already running');
57
 
58
  const tempDir = `/tmp/zbr-${discordId}-${botId}`;
59
  fs.mkdirSync(tempDir, { recursive: true });
60
+
61
+ fs.writeFileSync(path.join(tempDir, '.env'), envFile);
62
+ fs.writeFileSync(path.join(tempDir, 'zbr.json'), zbrJson);
63
+
 
 
 
 
 
64
  const commandsDir = path.join(tempDir, 'commands');
65
  fs.mkdirSync(commandsDir, { recursive: true });
66
  commands.forEach(cmd => {
67
+ fs.writeFileSync(path.join(commandsDir, cmd.filename), cmd.content);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  });
69
 
70
+ fs.writeFileSync(path.join(tempDir, 'zbr.db'), Buffer.from(dbBase64, 'base64'));
71
+
72
+ const child = spawn('/usr/local/bin/zbr', [], {
73
+ cwd: tempDir,
74
+ stdio: ['ignore', 'pipe', 'pipe']
75
+ });
76
 
77
+ if (child.stdout) {
78
+ child.stdout.on('data', (data) => console.log(data.toString()));
79
+ }
80
+ if (child.stderr) {
81
+ child.stderr.on('data', (data) => console.error(data.toString()));
82
+ }
83
 
84
  processes.set(key, { child, tempDir });
85
 
 
90
  res.json({ success: true, status: 'running' });
91
  });
92
 
93
+ function stopBot(key: string): boolean {
94
  const proc = processes.get(key);
95
  if (!proc) return false;
96
  proc.child.kill();
 
99
  return true;
100
  }
101
 
102
+ app.post('/stop', (req: Request<{}, any, StopRequestBody>, res: Response) => {
103
  const { botId, discordId } = req.body;
104
+ if (stopBot(`${discordId}-${botId}`)) {
105
+ res.json({ success: true, status: 'stopped' });
106
+ } else {
107
+ res.status(404).send('Bot not running');
108
+ }
109
  });
110
 
111
+ app.get('/status/:discordId/:botId', (req: Request, res: Response) => {
112
  const { discordId, botId } = req.params;
113
  res.json({ status: processes.has(`${discordId}-${botId}`) ? 'running' : 'stopped' });
114
  });
115
 
116
+ app.get('/health', (req: Request, res: Response) => res.json({ ok: true }));
117
 
118
  app.listen(7860, () => console.log('Server running on port 7860'));
tsconfig.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "outDir": "./dist",
6
+ "rootDir": "./src",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true
11
+ },
12
+ "include": ["src/**/*"]
13
+ }