Update package version v5.1.2 #472

Closed
github-actions[bot] wants to merge 2 commits from update-version into main
7 changed files with 110 additions and 564 deletions

101
README.md
View File

@@ -10,104 +10,3 @@ A quick and simple way to create and manage Minecraft servers like `Bedrock`, `J
## Wiki
We are moving the documentation [here](https://wiki.bdsmaneger.sirherobrine23.org/).
## Example
With yargs and cli-color ([This is the cli](https://github.com/The-Bds-Maneger/bds-cli)).
```typescript
#!/usr/bin/env node
import readline from "node:readline";
import yargs from "yargs";
import cliColors from "cli-color";
import * as BdsCore from "@the-bds-maneger/core";
// type currentPlatform = "Bedrock"|"Java"|"Spigot"|"PocketmineMP"|"Powernukkit";
const Yargs = yargs(process.argv.slice(2)).help().version(false).alias("h", "help").wrap(yargs.terminalWidth());
// Bds import/export
Yargs.command("import", "import from another computer", async yargs => {
const options = yargs.options("host", {
type: "string"
}).options("port", {
type: "number"
}).option("authToken", {
type: "string",
demandOption: true,
required: true
}).parseSync();
return BdsCore.importBds({host: options.host, port: options.port, authToken: options.authToken});
}).command("export", "Export bds root folder", async yargs => {
const opts = yargs.option("port", {
type: "number",
description: "listen port server, default is random"
}).parseSync();
const server = new BdsCore.exportBds();
await server.listen(opts.port);
return server.waitClose();
});
const addPlatform = (Yargs) => Yargs.option("platform", {
alias: "P",
description: "Select Bds Maneger core platform",
demandOption: true,
type: "string",
choices: [
"Bedrock",
"Java",
"Spigot",
"PocketmineMP",
"Powernukkit",
"Paper"
]
});
// Install Server
Yargs.command("install", "Download and Install server", yargs => {
addPlatform(yargs);
const options = yargs.option("version", {alias: "v", description: "Server version", default: "latest"}).parseSync();
if (options.platform === "Bedrock") return BdsCore.Bedrock.installServer(options.version);
else if (options.platform === "Java") return BdsCore.Java.installServer(options.version);
else if (options.platform === "Spigot") return BdsCore.Spigot.installServer(options.version);
else if (options.platform === "Paper") return BdsCore.PaperMC.installServer(options.version);
else if (options.platform === "PocketmineMP") return BdsCore.PocketmineMP.installServer(options.version);
else if (options.platform === "Powernukkit") return BdsCore.Powernukkit.installServer(options.version);
throw new Error("Invalid platform");
});
// Start Server
Yargs.command("run", "Start server", async yargs => {
addPlatform(yargs);
const options = yargs.option("javaMaxMemory", {alias: "M", type: "number"}).option("javaAllFreeMem", {alias: "F", type: "boolean", default: true, description: "Use all free memory to run Java server"}).option("installGeyser", {alias: "g", type: "boolean", description: "Install geyser plugin to supported servers"}).parseSync();
let server: BdsCore.globalPlatfroms.actions;
if (options.platform === "Bedrock") server = await BdsCore.Bedrock.startServer();
else if (options.platform === "Java") server = await BdsCore.Java.startServer({maxMemory: options.javaMaxMemory});
else if (options.platform === "Spigot") server = await BdsCore.Spigot.startServer({maxMemory: options.javaMaxMemory, maxFreeMemory: options.javaAllFreeMem, pluginList: options.installGeyser ? ["Geyser"]:undefined});
else if (options.platform === "Paper") server = await BdsCore.PaperMC.startServer({maxMemory: options.javaMaxMemory, maxFreeMemory: options.javaAllFreeMem, pluginList: options.installGeyser ? ["Geyser"]:undefined});
else if (options.platform === "PocketmineMP") server = await BdsCore.PocketmineMP.startServer();
else if (options.platform === "Powernukkit") server = await BdsCore.Powernukkit.startServer({maxMemory: options.javaMaxMemory});
else throw new Error("Invalid platform");
server.on("log_stderr", data => console.log(cliColors.redBright(data)));
server.on("log_stdout", data => console.log(cliColors.greenBright(data)));
server.once("serverStarted", () => {
let log = "";
server.portListening.forEach(port => {
log += `Port listen: ${port.port}\n${"\tTo: "+(port.plugin === "geyser"?"Bedrock":(port.plugin||options.platform)+"\n")}`;
});
console.log(log.trim());
console.log(cliColors.yellowBright("Commands inputs now avaible"))
const line = readline.createInterface({input: process.stdin, output: process.stdout});
line.on("line", line => server.runCommand(line));
line.once("SIGINT", () => server.stopServer());
line.once("SIGCONT", () => server.stopServer());
line.once("SIGTSTP", () => server.stopServer());
server.once("exit", () => line.close());
});
return server.waitExit();
});
// Plugin maneger
// Yargs.command("plugin", "Plugin maneger", yargs=>yargs.command("install", "Install plugin", yargs => yargs, () => {}).command({command: "*", handler: () => {Yargs.showHelp();}}), ()=>{});
Yargs.command({command: "*", handler: () => {Yargs.showHelp();}}).parseAsync();
```

210
package-lock.json generated
View File

@@ -1,22 +1,19 @@
{
"name": "@the-bds-maneger/core",
"version": "5.0.2",
"version": "5.1.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@the-bds-maneger/core",
"version": "5.0.2",
"version": "5.1.1",
"license": "GPL-3.0",
"dependencies": {
"@the-bds-maneger/server_versions": "^4.2.0",
"adm-zip": "^0.5.9",
"cron": "^2.1.0",
"express": "^4.18.2",
"express-rate-limit": "^6.6.0",
"got": "^12.5.2",
"prismarine-nbt": "^2.2.1",
"prom-client": "^14.1.0",
"tar": "^6.1.11"
},
"bin": {
@@ -25,7 +22,6 @@
"devDependencies": {
"@types/adm-zip": "^0.5.0",
"@types/cron": "^2.0.0",
"@types/express": "^4.17.14",
"@types/mocha": "^10.0.0",
"@types/node": "^18.11.0",
"@types/tar": "^6.1.3",
@@ -155,25 +151,6 @@
"@types/node": "*"
}
},
"node_modules/@types/body-parser": {
"version": "1.19.2",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
"integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
"dev": true,
"dependencies": {
"@types/connect": "*",
"@types/node": "*"
}
},
"node_modules/@types/connect": {
"version": "3.4.35",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
"integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/cron": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.0.0.tgz",
@@ -184,29 +161,6 @@
"@types/node": "*"
}
},
"node_modules/@types/express": {
"version": "4.17.14",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz",
"integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==",
"dev": true,
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.18",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"node_modules/@types/express-serve-static-core": {
"version": "4.17.31",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz",
"integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==",
"dev": true,
"dependencies": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
"node_modules/@types/http-cache-semantics": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
@@ -218,12 +172,6 @@
"integrity": "sha512-/LAvk1cMOJt0ghzMFrZEvByUhsiEfeeT2IF53Le+Ki3A538yEL9pRZ7a6MuCxdrYK+YNqNIDmrKU/r2nnw04zQ==",
"dev": true
},
"node_modules/@types/mime": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==",
"dev": true
},
"node_modules/@types/mocha": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.0.tgz",
@@ -235,28 +183,6 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz",
"integrity": "sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w=="
},
"node_modules/@types/qs": {
"version": "6.9.7",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
"dev": true
},
"node_modules/@types/range-parser": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
"dev": true
},
"node_modules/@types/serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz",
"integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==",
"dev": true,
"dependencies": {
"@types/mime": "*",
"@types/node": "*"
}
},
"node_modules/@types/tar": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.3.tgz",
@@ -490,11 +416,6 @@
"node": ">=8"
}
},
"node_modules/bintrees": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz",
"integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw=="
},
"node_modules/body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
@@ -1105,17 +1026,6 @@
"node": ">= 0.10.0"
}
},
"node_modules/express-rate-limit": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz",
"integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==",
"engines": {
"node": ">= 12.9.0"
},
"peerDependencies": {
"express": "^4 || ^5"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -2366,17 +2276,6 @@
"protodef": "^1.9.0"
}
},
"node_modules/prom-client": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.1.0.tgz",
"integrity": "sha512-iFWCchQmi4170omLpFXbzz62SQTmPhtBL35v0qGEVRHKcqIeiexaoYeP0vfZTujxEq3tA87iqOdRbC9svS1B9A==",
"dependencies": {
"tdigest": "^0.1.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/protodef": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/protodef/-/protodef-1.15.0.tgz",
@@ -2805,14 +2704,6 @@
"node": ">= 10"
}
},
"node_modules/tdigest": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz",
"integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==",
"dependencies": {
"bintrees": "1.0.2"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -3370,25 +3261,6 @@
"@types/node": "*"
}
},
"@types/body-parser": {
"version": "1.19.2",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
"integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
"dev": true,
"requires": {
"@types/connect": "*",
"@types/node": "*"
}
},
"@types/connect": {
"version": "3.4.35",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
"integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/cron": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.0.0.tgz",
@@ -3399,29 +3271,6 @@
"@types/node": "*"
}
},
"@types/express": {
"version": "4.17.14",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz",
"integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==",
"dev": true,
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.18",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"@types/express-serve-static-core": {
"version": "4.17.31",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz",
"integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==",
"dev": true,
"requires": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
"@types/http-cache-semantics": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
@@ -3433,12 +3282,6 @@
"integrity": "sha512-/LAvk1cMOJt0ghzMFrZEvByUhsiEfeeT2IF53Le+Ki3A538yEL9pRZ7a6MuCxdrYK+YNqNIDmrKU/r2nnw04zQ==",
"dev": true
},
"@types/mime": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==",
"dev": true
},
"@types/mocha": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.0.tgz",
@@ -3450,28 +3293,6 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.0.tgz",
"integrity": "sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w=="
},
"@types/qs": {
"version": "6.9.7",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
"dev": true
},
"@types/range-parser": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
"dev": true
},
"@types/serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz",
"integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==",
"dev": true,
"requires": {
"@types/mime": "*",
"@types/node": "*"
}
},
"@types/tar": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.3.tgz",
@@ -3645,11 +3466,6 @@
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true
},
"bintrees": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz",
"integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw=="
},
"body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
@@ -4088,12 +3904,6 @@
"vary": "~1.1.2"
}
},
"express-rate-limit": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz",
"integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==",
"requires": {}
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -4990,14 +4800,6 @@
"protodef": "^1.9.0"
}
},
"prom-client": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.1.0.tgz",
"integrity": "sha512-iFWCchQmi4170omLpFXbzz62SQTmPhtBL35v0qGEVRHKcqIeiexaoYeP0vfZTujxEq3tA87iqOdRbC9svS1B9A==",
"requires": {
"tdigest": "^0.1.1"
}
},
"protodef": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/protodef/-/protodef-1.15.0.tgz",
@@ -5319,14 +5121,6 @@
"yallist": "^4.0.0"
}
},
"tdigest": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz",
"integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==",
"requires": {
"bintrees": "1.0.2"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "@the-bds-maneger/core",
"version": "5.1.1",
"version": "5.1.2",
"description": "A very simple way to manage Minecraft servers",
"author": "Sirherobrine23",
"license": "GPL-3.0",
@@ -31,24 +31,17 @@
"engines": {
"node": ">=16.0.0"
},
"bin": {
"bdsd": "./src/bdsd.js"
},
"dependencies": {
"@the-bds-maneger/server_versions": "^4.2.0",
"adm-zip": "^0.5.9",
"cron": "^2.1.0",
"express": "^4.18.2",
"express-rate-limit": "^6.6.0",
"got": "^12.5.2",
"prismarine-nbt": "^2.2.1",
"prom-client": "^14.1.0",
"tar": "^6.1.11"
},
"devDependencies": {
"@types/adm-zip": "^0.5.0",
"@types/cron": "^2.0.0",
"@types/express": "^4.17.14",
"@types/mocha": "^10.0.0",
"@types/node": "^18.11.0",
"@types/tar": "^6.1.3",

View File

@@ -1,207 +0,0 @@
#!/usr/bin/env node
import os from "node:os";
import fs from "node:fs";
import fsPromise from "node:fs/promises";
import path from "node:path";
import crypto from "node:crypto";
import express from "express";
import expressRateLimit from "express-rate-limit";
import * as bdsCore from "./index";
import * as Prometheus from "prom-client";
process.on("unhandledRejection", err => console.trace(err));
Prometheus.collectDefaultMetrics({prefix: "bdsd"});
const requests = new Prometheus.Counter({
name: "bdsd_requests",
help: "Total number of requests to the Server",
labelNames: ["method", "from", "path"]
});
const app = express();
const bdsdAuth = path.join(bdsCore.platformPathManeger.bdsRoot, "bdsd_auth.json");
const sockListen = path.join(os.tmpdir(), "bdsd.sock");
if (fs.existsSync(sockListen)) fs.rmSync(sockListen, {force: true});
app.disable("x-powered-by").disable("etag");
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(({ res, next }) => { res.json = (body: any) => res.setHeader("Content-Type", "application/json").send(JSON.stringify(body, null, 2)); return next(); });
app.get("/metrics", async ({res, next}) => Prometheus.register.metrics().then(data => res.set("Content-Type", Prometheus.register.contentType).send(data)).catch(err => next(err)));
app.use((req, _, next) => {requests.inc({method: req.method, path: req.path, from: !(req.socket.remoteAddress&&req.socket.remotePort)?"socket":req.protocol});next();});
app.use(expressRateLimit({skipSuccessfulRequests: true, message: "Already reached the limit, please wait a few moments", windowMs: (1000*60)*2, max: 1500}));
if (process.env.BDSD_IGNORE_KEY) console.warn("Bdsd ignore auth key!");
app.use(async (req, res, next) => {
// Allow by default socket
if (!req.socket.remoteAddress && !req.socket.remotePort) {
res.setHeader("AuthSocket", "true");
return next();
}
// External requests
if (process.env.BDSD_IGNORE_KEY) return next();
if (!fs.existsSync(bdsdAuth)) {
if (!fs.existsSync(bdsCore.platformPathManeger.bdsRoot)) await fsPromise.mkdir(bdsCore.platformPathManeger.bdsRoot, {recursive: true});
const keys = crypto.generateKeyPairSync("rsa", {modulusLength: 4096, publicKeyEncoding: {type: "spki", format: "pem"}, privateKeyEncoding: {type: "pkcs8", format: "pem", cipher: "aes-256-cbc", passphrase: crypto.randomBytes(128).toString("hex")}});
await fsPromise.writeFile(bdsdAuth, JSON.stringify(keys, null, 2));
console.log("Bdsd Keys\nPublic base64: '%s'\n\npublic:\n%s", Buffer.from(keys.publicKey).toString("base64"), keys.publicKey);
return res.status(204).json({
message: "Generated keys, re-auth with new public key!"
});
}
if (!req.headers.authorization) return res.status(400).json({error: "Send authorization with public key!"});
const authorizationPub = Buffer.from(req.headers.authorization.replace(/^.*\s+/, ""), "base64").toString("utf8").trim();
const publicKey = (JSON.parse(await fsPromise.readFile(bdsdAuth, "utf8")) as crypto.KeyPairSyncResult<string, string>).publicKey.trim();
if (publicKey === authorizationPub) return next();
return res.status(400).json({
error: "Invalid auth or incorret public key"
});
});
// Listen socks
app.listen(sockListen, function () {console.info("Socket listen on '%s'", this.address());});
if (process.env.PORT) app.listen(process.env.PORT, () => console.info("HTTP listen on http://127.0.0.1:%s", process.env.PORT));
let timesBefore = os.cpus().map(c => c.times);
function getAverageUsage() {
let timesAfter = os.cpus().map(c => c.times);
let timeDeltas = timesAfter.map((t, i) => ({
user: t.user - timesBefore[i].user,
sys: t.sys - timesBefore[i].sys,
idle: t.idle - timesBefore[i].idle
}));
timesBefore = timesAfter;
return Math.floor(timeDeltas.map(times => 1 - times.idle / (times.user + times.sys + times.idle)).reduce((l1, l2) => l1 + l2) / timeDeltas.length*100);
}
app.get("/", ({res}) => {
return res.status(200).json({
platform: process.platform,
arch: process.arch,
cpu: {
avg: getAverageUsage(),
cores: os.cpus().length,
},
});
});
// v1 routes
const app_v1 = express.Router();
app.use("/v1", app_v1);
// Send Sessions
app_v1.get("/", ({res}) => res.json(Object.keys(bdsCore.globalPlatfroms.internalSessions).map(key => {
return {
id: bdsCore.globalPlatfroms.internalSessions[key].id,
platform: bdsCore.globalPlatfroms.internalSessions[key].platform,
serverStarted: bdsCore.globalPlatfroms.internalSessions[key].serverStarted,
portListen: bdsCore.globalPlatfroms.internalSessions[key].portListening,
playerActions: bdsCore.globalPlatfroms.internalSessions[key].playerActions,
};
})));
// Install server
app_v1.put("/server", async (req, res, next) => {
try {
if (!req.body||Object.keys(req.body).length === 0) return res.status(400).json({
error: "Body is empty"
});
const action = req.body.action as "install"|"start";
const platform = req.body.platform as bdsCore.platformPathManeger.bdsPlatform;
if (action === "install" && req.body.version === undefined) req.body.version = "latest";
if (platform === "bedrock") {
if (action === "install") return res.json(await bdsCore.Bedrock.installServer(req.body.version, req.body.platformOptions));
else if (action === "start") {
const platform = await bdsCore.Bedrock.startServer(req.body.platformOptions);
return res.json({
id: platform.id
});
}
} else if (platform === "pocketmine") {
if (action === "install") return res.json(await bdsCore.PocketmineMP.installServer(req.body.version, req.body.platformOptions));
else if (action === "start") {
const platform = await bdsCore.PocketmineMP.startServer(req.body.platformOptions);
return res.json({
id: platform.id
});
}
} else if (platform === "java") {
if (action === "install") return res.json(await bdsCore.Java.installServer(req.body.version, req.body.platformOptions));
else if (action === "start") {
const platform = await bdsCore.Java.startServer(req.body.javaOptions);
return res.json({
id: platform.id
});
}
} else if (platform === "paper") {
if (action === "install") return res.json(await bdsCore.PaperMC.installServer(req.body.version, req.body.platformOptions));
else if (action === "start") {
const platform = await bdsCore.PaperMC.startServer(req.body.javaOptions);
return res.json({
id: platform.id
});
}
} else if (platform === "spigot") {
if (action === "install") return res.json(await bdsCore.Spigot.installServer(req.body.version, req.body.platformOptions));
else if (action === "start") {
const platform = await bdsCore.Spigot.startServer(req.body.javaOptions);
return res.json({
id: platform.id
});
}
} else if (platform === "powernukkit") {
if (action === "install") return res.json(await bdsCore.Powernukkit.installServer(req.body.version, req.body.platformOptions));
else if (action === "start") {
const platform = await bdsCore.Powernukkit.startServer(req.body.javaOptions);
return res.json({
id: platform.id
});
}
}} catch(err) {
return next(err);
}
return res.status(400).json({
error: "Invalid action"
});
});
app_v1.get("/log/:id", (req, res) => {
const session = bdsCore.globalPlatfroms.internalSessions[req.params.id];
if (!session) return res.status(400).json({error: "Session ID not exists!"});
res.status(200);
if (session.serverCommand.options?.logPath?.stdout) fs.createReadStream(session.serverCommand.options.logPath.stdout, {autoClose: false, emitClose: false}).on("data", data => res.write(data));
session.events.on("log", data => res.write(Buffer.from(data+"\n")));
session.events.once("exit", () => {if (res.closed) res.end()});
return res;
});
app_v1.put("/command/:id", (req, res) => {
const session = bdsCore.globalPlatfroms.internalSessions[req.params.id];
if (!session) return res.status(400).json({error: "Session ID not exists!"});
session.runCommand(req.body?.command);
return res;
});
app_v1.get("/stop/:id", (req, res, next) => {
const session = bdsCore.globalPlatfroms.internalSessions[req.params.id];
if (!session) return res.status(400).json({error: "Session ID not exists!"});
return session.stopServer().then(exitCode => res.status(200).json({exitCode})).catch(err => next(err));
});
// v2
const app_v2 = express.Router();
app.use("/v2", app_v2);
// list sessions
app_v2.get("/", async (req, res) => {});
// Errors pages
app.all("*", (req, res) => res.status(404).json({
error: "Page not found",
path: req.path
}));
app.use((error, _1, res, _3) => {
return res.status(500).json({
internalError: String(error).replace(/Error:\s+/, ""),
});
});

View File

@@ -1,14 +1,37 @@
export * as platformPathManeger from "./platformPathManeger"
export * as globalPlatfroms from "./globalPlatfroms";
export * as pluginManeger from "./plugin/plugin";
export * as export_import from "./export_import";
export * as process_load from "./lib/processLoad";
export * as PocketmineMP from "./pocketmine";
export * as pluginHooks from "./plugin/hook";
export * as Powernukkit from "./pwnuukit";
export * as httpRequest from "./lib/httpRequest";
export * as PaperMC from "./paper";
export * as Bedrock from "./bedrock";
export * as Spigot from "./spigot";
export * as proxy from "./lib/proxy";
export * as Java from "./java";
// Utils
import * as httpRequest from "./lib/httpRequest";
import * as platformPathManeger from "./platformPathManeger"
import * as globalPlatfroms from "./globalPlatfroms";
import * as pluginManeger from "./plugin/plugin";
import * as export_import from "./export_import";
import * as process_load from "./lib/processLoad";
import * as pluginHooks from "./plugin/hook";
import * as proxy from "./lib/proxy";
// Platforms
import * as Bedrock from "./bedrock";
import * as Java from "./java";
import * as PocketmineMP from "./pocketmine";
import * as Spigot from "./spigot";
import * as Powernukkit from "./pwnuukit";
import * as PaperMC from "./paper";
export {platformPathManeger, globalPlatfroms, pluginManeger, export_import, process_load, PocketmineMP, pluginHooks, Powernukkit, httpRequest, PaperMC, Bedrock, Spigot, proxy, Java};
export default {
Bedrock,
Java,
PocketmineMP,
Powernukkit,
PaperMC,
Spigot,
utils: {
platformPathManeger,
globalPlatfroms,
pluginManeger,
pluginHooks,
httpRequest,
export_import,
process_load,
proxy
}
};

View File

@@ -1,13 +1,69 @@
import { tmpdir } from "node:os";
import fs from "node:fs";
import path from "node:path";
import type { Method } from "got";
import tar from "tar";
import AdmZip from "adm-zip";
let got: (typeof import("got"))["default"];
const gotCjs = async () => got||(await (eval('import("got")') as Promise<typeof import("got")>)).default;
const gotCjs = async () => got||(await (eval('import("got")') as Promise<typeof import("got")>)).default.extend({enableUnixSockets: true});
gotCjs().then(res => got = res);
export type requestOptions = {
path?: string,
url?: string,
socket?: {path: string, protocoll?: "http"|"https"},
method?: Method,
headers?: {[headerName: string]: string[]|string},
body?: any,
};
export async function pipeFetch(options: requestOptions & {stream: fs.WriteStream}) {
let urlRequest: string;
if (options.url) urlRequest = options.url+options.path;
else if (options.socket) urlRequest = `${options.socket.protocoll||"http"}://unix:${options.socket.path}:${options.path||"/"}`;
else throw new Error("Enter a url or an (IPC/Unix) socket");
const gotStream = (await gotCjs()).stream(urlRequest, {
isStream: true,
headers: (!options.headers)?{}:options.headers,
method: options.method||"GET",
body: options.body,
});
await new Promise<void>((done, reject) => {
options.stream.on("error", reject);
gotStream.on("error", reject);
gotStream.once("end", () => options.stream.once("finish", done));
});
}
export async function bufferFetch(options: requestOptions) {
let urlRequest: string;
if (options.url) urlRequest = options.url+options.path;
else if (options.socket) urlRequest = `${options.socket.protocoll||"http"}://unix:${options.socket.path}:${options.path||"/"}`;
else throw new Error("Enter a url or an (IPC/Unix) socket");
return gotCjs().then(request => request(urlRequest, {
headers: (!options.headers)?{}:options.headers,
method: options.method||"GET",
body: options.body,
responseType: "buffer",
})).then(res => ({headers: res.headers, data: Buffer.from(res.body), response: res}));
}
export async function getBuffer(url: string, options?: {method?: string, body?: any, headers?: {[key: string]: string}}): Promise<Buffer> {
const urlPar = new URL(url);
return bufferFetch({
path: urlPar.pathname,
url: urlPar.protocol+"//"+urlPar.host,
headers: options?.headers,
body: options?.body,
method: options.method as any
}).then(({data}) => data);
}
export async function getJSON<JSONReturn = any>(url: string|requestOptions, options?: requestOptions): Promise<JSONReturn> {
return bufferFetch(typeof url === "string"?{...(options||{}), url}:url).then(res => JSON.parse(res.data.toString("utf8")) as JSONReturn);
}
export async function saveFile(url: string, options?: {filePath?: string, headers?: {[key: string]: string|number}}) {
const Headers = {};
let fileSave = path.join(tmpdir(), Date.now()+"_raw_bdscore_"+path.basename(url));
@@ -27,21 +83,6 @@ export async function saveFile(url: string, options?: {filePath?: string, header
return fileSave;
}
export async function getBuffer(url: string, options?: {method?: string,body?: any, headers?: {[key: string]: string}}): Promise<Buffer> {
const Headers = {};
let Body: any;
if (options) {
if (options.headers) Object.keys(options.headers).forEach(key => Headers[key] = options.headers[key]);
if (options.body) Body = options.body;
}
return (await gotCjs())(url, {
headers: Headers,
body: Body,
method: (options?.method||"GET").toUpperCase() as any,
responseType: "buffer"
}).then(({body}) => Buffer.from(body));
}
export async function tarExtract(url: string, options?: {folderPath?: string, headers?: {[key: string]: string|number}}) {
let fileSave = path.join(tmpdir(), "_bdscore", Date.now()+"_raw_bdscore");
const Headers = {};
@@ -92,14 +133,6 @@ export async function extractZip(url: string, folderTarget: string) {
return extract(folderTarget);
}
export async function getJSON<JSONReturn = any>(url: string, options?: {method?: string, body?: any, headers?: {[key: string]: string}}): Promise<JSONReturn> {
return getBuffer(url, {
body: options?.body,
headers: options?.headers,
method: options?.method
}).then(res => JSON.parse(res.toString("utf8")) as JSONReturn);
}
export type testIpv6 = {
ip: string,
type: "ipv4"|"ipv6",

View File

@@ -113,8 +113,19 @@ export async function changeDefault(platform: bdsPlatform, id: bdsPlatformOption
*/
export async function getIds(platform?: bdsPlatform) {
if (!platform) {
const platformIds: {[platform: string]: string[]} = {};
await Promise.all((await fs.readdir(bdsRoot)).map(platforms => fs.readdir(path.join(bdsRoot, platforms)).then(data => platformIds[platforms] = data.filter(folder => folder !== "default"))));
const platformIds: {[platform: string]: {id: string, realID?: string}[]} = {};
if (!await exists(bdsRoot)) return platformIds;
const Platforms = await fs.readdir(bdsRoot);
if (Platforms.filter(folder => !platformArray.includes(folder as bdsPlatform)).length > 0) throw new Error("Old or invalid Platform path.");
for (const Platform of Platforms) {
for (const id of await fs.readdir(path.join(bdsRoot, Platform))) {
if (!platformIds[Platform]) platformIds[Platform] = []
const idPlatform = path.join(bdsRoot, Platform, id);
const realPath = await fs.realpath(idPlatform);
if (idPlatform !== realPath) platformIds[Platform].push({id, realID: path.basename(realPath)});
else platformIds[Platform].push({id});
}
}
return platformIds;
}
if (!platformArray.includes(platform)) throw new Error("Invalid platform");