From b450a35a245e6f02d4a61b18203917ea946e50f6 Mon Sep 17 00:00:00 2001 From: Matheus Sampaio Queiroga Date: Thu, 20 Oct 2022 23:22:30 +0000 Subject: [PATCH 1/3] remove bdsd and packages update httpRequest --- README.md | 101 ------------------ package-lock.json | 210 +------------------------------------ package.json | 9 +- src/bdsd.ts | 207 ------------------------------------ src/index.ts | 51 ++++++--- src/lib/httpRequest.ts | 81 +++++++++----- src/platformPathManeger.ts | 15 ++- 7 files changed, 110 insertions(+), 564 deletions(-) delete mode 100644 src/bdsd.ts diff --git a/README.md b/README.md index 90b2d18..8b5283e 100644 --- a/README.md +++ b/README.md @@ -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(); -``` diff --git a/package-lock.json b/package-lock.json index 37f9ac2..cbb5368 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 66cf2e7..db0c64e 100644 --- a/package.json +++ b/package.json @@ -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", @@ -57,4 +50,4 @@ "typedoc": "^0.23.16", "typescript": "^4.8.4" } -} \ No newline at end of file +} diff --git a/src/bdsd.ts b/src/bdsd.ts deleted file mode 100644 index bbce3cd..0000000 --- a/src/bdsd.ts +++ /dev/null @@ -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).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+/, ""), - }); -}); \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 1751810..a3859f8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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 + } +}; \ No newline at end of file diff --git a/src/lib/httpRequest.ts b/src/lib/httpRequest.ts index 2167fbc..9982766 100644 --- a/src/lib/httpRequest.ts +++ b/src/lib/httpRequest.ts @@ -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)).default; +const gotCjs = async () => got||(await (eval('import("got")') as Promise)).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((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 { + 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(url: string|requestOptions, options?: requestOptions): Promise { + 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 { - 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(url: string, options?: {method?: string, body?: any, headers?: {[key: string]: string}}): Promise { - 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", diff --git a/src/platformPathManeger.ts b/src/platformPathManeger.ts index 5737b37..12ff18f 100644 --- a/src/platformPathManeger.ts +++ b/src/platformPathManeger.ts @@ -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"); -- 2.51.0 From 6cc7e8ddd12994d93b732257b2b6a7391861b84f Mon Sep 17 00:00:00 2001 From: Sirherobrine23 Date: Thu, 20 Oct 2022 23:24:16 +0000 Subject: [PATCH 2/3] Update version v5.1.2 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index db0c64e..74223c8 100644 --- a/package.json +++ b/package.json @@ -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", @@ -50,4 +50,4 @@ "typedoc": "^0.23.16", "typescript": "^4.8.4" } -} +} \ No newline at end of file -- 2.51.0 From adf7638cb393cf35ac83e6649468c52a1eedbabb Mon Sep 17 00:00:00 2001 From: Matheus Sampaio Queiroga Date: Thu, 20 Oct 2022 23:22:30 +0000 Subject: [PATCH 3/3] remove bdsd and packages update httpRequest --- README.md | 101 ------------------ package-lock.json | 210 +------------------------------------ package.json | 9 +- src/bdsd.ts | 207 ------------------------------------ src/index.ts | 51 ++++++--- src/lib/httpRequest.ts | 81 +++++++++----- src/platformPathManeger.ts | 15 ++- 7 files changed, 110 insertions(+), 564 deletions(-) delete mode 100644 src/bdsd.ts diff --git a/README.md b/README.md index 90b2d18..8b5283e 100644 --- a/README.md +++ b/README.md @@ -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(); -``` diff --git a/package-lock.json b/package-lock.json index 37f9ac2..cbb5368 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 66cf2e7..db0c64e 100644 --- a/package.json +++ b/package.json @@ -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", @@ -57,4 +50,4 @@ "typedoc": "^0.23.16", "typescript": "^4.8.4" } -} \ No newline at end of file +} diff --git a/src/bdsd.ts b/src/bdsd.ts deleted file mode 100644 index bbce3cd..0000000 --- a/src/bdsd.ts +++ /dev/null @@ -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).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+/, ""), - }); -}); \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 1751810..a3859f8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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 + } +}; \ No newline at end of file diff --git a/src/lib/httpRequest.ts b/src/lib/httpRequest.ts index 2167fbc..df1ccfc 100644 --- a/src/lib/httpRequest.ts +++ b/src/lib/httpRequest.ts @@ -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)).default; +const gotCjs = async () => got||(await (eval('import("got")') as Promise)).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((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 { + 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(url: string|requestOptions, options?: requestOptions): Promise { + 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 { - 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(url: string, options?: {method?: string, body?: any, headers?: {[key: string]: string}}): Promise { - 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", diff --git a/src/platformPathManeger.ts b/src/platformPathManeger.ts index 5737b37..12ff18f 100644 --- a/src/platformPathManeger.ts +++ b/src/platformPathManeger.ts @@ -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"); -- 2.51.0