Update actions and Bucket upload script #526
							
								
								
									
										53
									
								
								.github/uploadToBucket.mjs
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										53
									
								
								.github/uploadToBucket.mjs
									
									
									
									
										vendored
									
									
								
							| @@ -1,38 +1,37 @@ | |||||||
| #!/usr/bin/env node | #!/usr/bin/env node | ||||||
| import { oracleBucket } from "@sirherobrine23/cloud"; | import { oracleBucket } from "@sirherobrine23/cloud"; | ||||||
| import { pipeline } from "node:stream/promises"; |  | ||||||
| import extendsFS from "@sirherobrine23/extends"; | import extendsFS from "@sirherobrine23/extends"; | ||||||
| import path from "node:path"; |  | ||||||
| import fs from "node:fs"; | import fs from "node:fs"; | ||||||
| const bucket = oracleBucket.oracleBucketPreAuth("sa-saopaulo-1", "grwodtg32n4d", "bdsFiles", process.env.ociauth || process.env.OCI_AUTHKEY); | import path from "node:path"; | ||||||
|  | import { finished } from "node:stream/promises"; | ||||||
| const args = process.argv.slice(2).map(String); | const args = process.argv.slice(2).map(String); | ||||||
|  | const bucket = oracleBucket.oracleBucketPreAuth("sa-saopaulo-1", "grwodtg32n4d", "bdsFiles", process.env.ociauth || process.env.OCI_AUTHKEY); | ||||||
|  |  | ||||||
| for (let argI = 0; argI < args.length; argI++) { | /** @type {string} */ | ||||||
|   if (args.at(argI).startsWith("-")) continue; | let arg; | ||||||
|   const file = path.resolve(process.cwd(), args.at(argI)); | while (!!(arg = args.shift())) { | ||||||
|   if (!(await extendsFS.exists(file))) { |   if (arg.startsWith("-")) continue; | ||||||
|     console.log("File %O dont exists!", file); |   let inPath, outPath; | ||||||
|     if (args.at(argI + 1) && args.at(argI + 1).startsWith("-")) argI++; |   let index; | ||||||
|   } |   if ((index = arg.indexOf(":")) === -1) outPath = path.relative(process.cwd(), (inPath = path.resolve(process.cwd(), arg))); | ||||||
|   let filename = path.basename(args.at(argI)); |   else { | ||||||
|   if (typeof filename === "string" && args.at(argI + 1) && args.at(argI + 1).startsWith("-")) { |     inPath = path.resolve(process.cwd(), arg.slice(0, index)); | ||||||
|     argI++; |     outPath = arg.slice(index+1); | ||||||
|     filename = args.at(argI).slice(1); |  | ||||||
|     while (filename.startsWith("-")) filename = filename.slice(1); |  | ||||||
|     filename.split(path.win32.sep).join(path.posix.sep); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (await extendsFS.isDirectory(file)) { |   if (!(await extendsFS.exists(inPath))) { | ||||||
|     const fileList = await extendsFS.readdirV2(file, true, (_1, _2, stats) => stats.isFile() || stats.isDirectory()); |     console.log("%O not exists", inPath); | ||||||
|     for (const file of fileList) { |     continue; | ||||||
|       if (extendsFS.isDirectory(file.fullPath)) continue; |   } | ||||||
|       console.log("Uploading %O to %O", file.fullPath, path.join(filename, file.path)); |  | ||||||
|       await pipeline(fs.createReadStream(file.fullPath), bucket.uploadFile(path.join(filename, file.path))); |   if (await extendsFS.isDirectory(inPath)) { | ||||||
|     } |     await extendsFS.readdirV2(inPath, true, () => true, async (relativePath, filePath, stats) => { | ||||||
|  |       if (stats.isDirectory()) return; | ||||||
|  |       console.log("Uploading %O to in Bucket %O", filePath, path.join(outPath, relativePath)); | ||||||
|  |       return finished(fs.createReadStream(filePath, "binary").pipe(bucket.uploadFile(path.join(outPath, relativePath)))); | ||||||
|  |     }); | ||||||
|   } else { |   } else { | ||||||
|     console.log("Uploading %O to %O", file, filename); |     console.log("Uploading %O to in Bucket %O", filePath, path.join(outPath, relativePath)); | ||||||
|     await pipeline(fs.createReadStream(file), bucket.uploadFile(filename)); |     await finished(fs.createReadStream(inPath, "binary").pipe(bucket.uploadFile(outPath))); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   console.log("Done!"); |  | ||||||
| } | } | ||||||
							
								
								
									
										2
									
								
								.github/workflows/phpBuild.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/phpBuild.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -216,7 +216,7 @@ jobs: | |||||||
|         path: ./phpOutput |         path: ./phpOutput | ||||||
|  |  | ||||||
|     - name: Upload to bucket |     - name: Upload to bucket | ||||||
|       run: node .github/uploadToBucket.mjs phpOutput -/php_bin |       run: node .github/uploadToBucket.mjs phpOutput:php_bin | ||||||
|       timeout-minutes: 25 |       timeout-minutes: 25 | ||||||
|       env: |       env: | ||||||
|         OCI_AUTHKEY: ${{ secrets.OCI_AUTHKEY }} |         OCI_AUTHKEY: ${{ secrets.OCI_AUTHKEY }} | ||||||
							
								
								
									
										23
									
								
								.github/workflows/publish.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								.github/workflows/publish.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -12,19 +12,6 @@ jobs: | |||||||
|     - uses: actions/checkout@v3 |     - uses: actions/checkout@v3 | ||||||
|       name: Code checkout |       name: Code checkout | ||||||
|  |  | ||||||
|     - name: Setup QEMU to Docker |  | ||||||
|       uses: docker/setup-qemu-action@v2 |  | ||||||
|  |  | ||||||
|     - name: Setup Buildx |  | ||||||
|       uses: docker/setup-buildx-action@v2 |  | ||||||
|  |  | ||||||
|     - name: Login into registry Github Packages |  | ||||||
|       uses: docker/login-action@v2 |  | ||||||
|       with: |  | ||||||
|         registry: ghcr.io |  | ||||||
|         username: ${{ github.actor }} |  | ||||||
|         password: ${{ secrets.GITHUB_TOKEN }} |  | ||||||
|  |  | ||||||
|     - uses: actions/setup-node@v3.6.0 |     - uses: actions/setup-node@v3.6.0 | ||||||
|       name: Setup node.js |       name: Setup node.js | ||||||
|       with: |       with: | ||||||
| @@ -41,13 +28,3 @@ jobs: | |||||||
|       run: npm --workspaces publish --access public --tag ${{ github.event.release.prerelease && 'next' || 'latest' }} |       run: npm --workspaces publish --access public --tag ${{ github.event.release.prerelease && 'next' || 'latest' }} | ||||||
|       env: |       env: | ||||||
|         NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |         NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||||||
|  |  | ||||||
|     - name: Build docker image |  | ||||||
|       uses: docker/build-push-action@v4 |  | ||||||
|       with: |  | ||||||
|         cache-from: type=gha,scope=sirherobrine23_docker |  | ||||||
|         cache-to: type=gha,scope=sirherobrine23_docker |  | ||||||
|         platforms: "linux/amd64,linux/arm64" |  | ||||||
|         context: ./ |  | ||||||
|         tags: ghcr.io/sirherobrine23/bdsmaneger |  | ||||||
|         push: true |  | ||||||
							
								
								
									
										2
									
								
								.github/workflows/spigotBuild.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/spigotBuild.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -54,7 +54,7 @@ jobs: | |||||||
|         path: artifacts |         path: artifacts | ||||||
|  |  | ||||||
|     - name: Upload to actifial |     - name: Upload to actifial | ||||||
|       run: node .github/uploadToBucket.mjs SpigotBuild artifacts |       run: node .github/uploadToBucket.mjs artifacts:SpigotBuild | ||||||
|       env: |       env: | ||||||
|         ociauth: "${{ secrets.OCI_AUTHKEY }}" |         ociauth: "${{ secrets.OCI_AUTHKEY }}" | ||||||
|         OCI_AUTHKEY: "${{ secrets.OCI_AUTHKEY }}" |         OCI_AUTHKEY: "${{ secrets.OCI_AUTHKEY }}" | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								.github/workflows/test.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								.github/workflows/test.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -9,11 +9,10 @@ jobs: | |||||||
|       fail-fast: false |       fail-fast: false | ||||||
|       matrix: |       matrix: | ||||||
|         package: |         package: | ||||||
|           - core |           - "@the-bds-maneger/core" | ||||||
|           - cli |           - "bds-maneger" | ||||||
|           - docker |           - "@the-bds-maneger/verapi" | ||||||
|           - verapi |     name: "Testing \"${{ matrix.package }}\"" | ||||||
|     name: "Testing ${{ matrix.package }}" |  | ||||||
|     env: |     env: | ||||||
|       bdscoreroot: "~/.bdsCore" |       bdscoreroot: "~/.bdsCore" | ||||||
|     steps: |     steps: | ||||||
| @@ -38,8 +37,8 @@ jobs: | |||||||
|  |  | ||||||
|     # Build Core |     # Build Core | ||||||
|     - name: Core Build |     - name: Core Build | ||||||
|       if: matrix.package != 'core' |       if: matrix.package != '@the-bds-maneger/core' | ||||||
|       run: npm run -w package/core build |       run: npm run -w "@the-bds-maneger/core" build | ||||||
|  |  | ||||||
|     - name: Build ${{ matrix.package }} |     - name: Build "${{ matrix.package }}" | ||||||
|       run: npm run --if-present -w "package/${{ matrix.package }}" build |       run: npm run --if-present -w "${{ matrix.package }}" prepack | ||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | |||||||
| # npm | # npm | ||||||
| /*.tgz | *.tgz | ||||||
|  |  | ||||||
| # Node | # Node | ||||||
| node_modules/ | node_modules/ | ||||||
| @@ -8,7 +8,7 @@ node_modules/ | |||||||
| # Typescript | # Typescript | ||||||
| **/*.js | **/*.js | ||||||
| **/*.d.ts | **/*.d.ts | ||||||
| **/tsconfig.tsbuildinfo | **/*.tsbuildinfo | ||||||
|  |  | ||||||
| # PHP and Spigot Pre builds | # PHP and Spigot Pre builds | ||||||
| phpOutput/ | phpOutput/ | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| # npm | # npm | ||||||
| /*.tgz | *.tgz | ||||||
|  |  | ||||||
| # Typescript | # Typescript | ||||||
| **/*.ts | **/*.ts | ||||||
| !**/*.d.ts | !**/*.d.ts | ||||||
| **/tsconfig.tsbuildinfo | **/*.tsbuildinfo | ||||||
|  |  | ||||||
| # PHP and Spigot Pre builds | # PHP and Spigot Pre builds | ||||||
| phpOutput/ | phpOutput/ | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @@ -6,9 +6,22 @@ | |||||||
|   "editor.minimap.enabled": false, |   "editor.minimap.enabled": false, | ||||||
|   "files.trimFinalNewlines": true, |   "files.trimFinalNewlines": true, | ||||||
|   "files.trimTrailingWhitespace": true, |   "files.trimTrailingWhitespace": true, | ||||||
|   // "files.exclude": { |   "editor.insertSpaces": true, | ||||||
|   //   "**/node_modules/": true, |   "editor.detectIndentation": false, | ||||||
|   //   "**/src/**/*.js": true, |   "editor.codeActionsOnSave": { | ||||||
|   //   "**/src/**/*.d.ts": true, |     "source.organizeImports": true | ||||||
|   // } |   }, | ||||||
|  |   "files.exclude": { | ||||||
|  |     "**/node_modules/": true, | ||||||
|  |     "packages/web/src/next/.next": true, | ||||||
|  |   }, | ||||||
|  |   "terminal.integrated.env.windows": { | ||||||
|  |     "PATH": "${workspaceFolder}/node_modules/.bin;${env:PATH}" | ||||||
|  |   }, | ||||||
|  |   "terminal.integrated.env.linux": { | ||||||
|  |     "PATH": "${workspaceFolder}/node_modules/.bin:${env:PATH}" | ||||||
|  |   }, | ||||||
|  |   "terminal.integrated.env.osx": { | ||||||
|  |     "PATH": "${workspaceFolder}/node_modules/.bin:${env:PATH}" | ||||||
|  |   } | ||||||
| } | } | ||||||
							
								
								
									
										13
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,13 +0,0 @@ | |||||||
| FROM node:lts |  | ||||||
| WORKDIR /app |  | ||||||
| COPY ./ ./ |  | ||||||
| RUN npm install --no-save && npm run -w package/docker build |  | ||||||
|  |  | ||||||
| FROM node:lts |  | ||||||
| WORKDIR /app |  | ||||||
| COPY --from=0 /app/package/docker ./ |  | ||||||
| RUN npm install |  | ||||||
| EXPOSE 3000:3000/tcp |  | ||||||
| ENV PORT=3000 |  | ||||||
| VOLUME [ "/data" ] |  | ||||||
| ENTRYPOINT "bash -c 'BDSCOREROOT=/data node src/index.js'" |  | ||||||
							
								
								
									
										11
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								package.json
									
									
									
									
									
								
							| @@ -9,13 +9,12 @@ | |||||||
|   "license": "GPL-3.0", |   "license": "GPL-3.0", | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@types/express": "^4.17.17", |     "@types/express": "^4.17.17", | ||||||
|     "@types/node": "^20.1.3", |     "@types/node": "^20.2.1", | ||||||
|     "typescript": "^5.0.4" |     "typescript": "4.9.5" | ||||||
|   }, |   }, | ||||||
|   "workspaces": [ |   "workspaces": [ | ||||||
|     "package/core", |     "packages/core", | ||||||
|     "package/cli", |     "packages/cli", | ||||||
|     "package/docker", |     "packages/verapi" | ||||||
|     "package/verapi" |  | ||||||
|   ] |   ] | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,8 +0,0 @@ | |||||||
| export * from "./serverManeger.js"; |  | ||||||
|  |  | ||||||
| import * as serverManeger from "./serverManeger.js"; |  | ||||||
| import * as Bedrock from "./servers/bedrock.js"; |  | ||||||
| import * as Java from "./servers/java.js"; |  | ||||||
|  |  | ||||||
| export default {...serverManeger, serverManeger, Bedrock, Java }; |  | ||||||
| export { serverManeger, Bedrock, Java }; |  | ||||||
| @@ -1,37 +0,0 @@ | |||||||
| # Bds Maneger Core |  | ||||||
|  |  | ||||||
| Basic core to install, update and manage several minecraft servers automatically, depending on a few dependencies, the basic being **Nodejs**. |  | ||||||
|  |  | ||||||
| ## Servers supports and TODO |  | ||||||
|  |  | ||||||
| **Bedrock Mojang**: |  | ||||||
|   - [x] Install/Update. |  | ||||||
|   - [ ] Hot backup. |  | ||||||
|   - [x] Start. |  | ||||||
|   - [x] Port Listened. |  | ||||||
|   - [ ] Player connect/disconnect/spawn. |  | ||||||
|   - [ ] Player kick/ban. |  | ||||||
|  |  | ||||||
| **Pocketmine PMMP**: |  | ||||||
|   - [x] Install/Update. |  | ||||||
|   - [ ] Hot backup. |  | ||||||
|   - [x] Start. |  | ||||||
|   - [ ] Port listened. |  | ||||||
|   - [ ] Player connect/disconnect. |  | ||||||
|   - [ ] Player kick/ban. |  | ||||||
|  |  | ||||||
| **Powernukkit** and **Cloudbust**: |  | ||||||
|   - [x] Install/Update. |  | ||||||
|   - 🚫 Hot backup. |  | ||||||
|   - [x] Start. |  | ||||||
|   - [ ] Port listened. |  | ||||||
|   - [ ] Player connect/disconnect. |  | ||||||
|   - [ ] Player kick/ban. |  | ||||||
|  |  | ||||||
| **Java Mojang**, **Purpur**, **Paper** and **Spigot**: |  | ||||||
|   - [x] Install/Update. |  | ||||||
|   - 🚫 Hot Backup. |  | ||||||
|   - [x] Start. |  | ||||||
|   - [ ] Port listened. |  | ||||||
|   - [ ] Player connect/disconect action. |  | ||||||
|   - [ ] Player kick/ban. |  | ||||||
| @@ -1,21 +0,0 @@ | |||||||
| { |  | ||||||
|   "name": "@the-bds-maneger/docker", |  | ||||||
|   "version": "6.0.1", |  | ||||||
|   "type": "module", |  | ||||||
|   "author": "Matheus Sampaio Queiroga <srherobrine20@gmail.com>", |  | ||||||
|   "license": "GPL-3.0", |  | ||||||
|   "private": true, |  | ||||||
|   "scripts": { |  | ||||||
|     "build": "tsc --build --clean && tsc --build" |  | ||||||
|   }, |  | ||||||
|   "dependencies": { |  | ||||||
|     "@the-bds-maneger/core": "^6.0.3", |  | ||||||
|     "express": "^4.18.2", |  | ||||||
|     "mongodb": "^5.5.0", |  | ||||||
|     "neste": "^1.0.2", |  | ||||||
|     "yaml": "^2.2.2" |  | ||||||
|   }, |  | ||||||
|   "devDependencies": { |  | ||||||
|     "@types/express": "^4.17.17" |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,137 +0,0 @@ | |||||||
| #!/usr/bin/env node |  | ||||||
| import bdsCore, { serverManeger, serverRun } from "@the-bds-maneger/core"; |  | ||||||
| import express from "express"; |  | ||||||
| import neste from "neste"; |  | ||||||
| import yaml from "yaml"; |  | ||||||
|  |  | ||||||
| const sessions: {[id: string]: serverRun} = {}; |  | ||||||
| process.on("exit", () => Object.keys(sessions).forEach(k => sessions[k].stopServer())); |  | ||||||
|  |  | ||||||
| // Catch error |  | ||||||
| for (const k of ["uncaughtException", "unhandledRejection"]) process.on(k, err => console.log(err)); |  | ||||||
| const app = neste(); |  | ||||||
| app.use(async (req, res, next) => { |  | ||||||
|   req.res.json = res.json = function(body: any) {return Object.assign(res, Promise.resolve(body).then(d => res.send(JSON.stringify(d, null, 2))).catch(next));} |  | ||||||
|   if (typeof req.headers["content-type"] === "string" && (["application/x-yaml", "text/yaml", "text/x-yaml"]).find(k => req.headers["content-type"].includes(k))) { |  | ||||||
|     const data: Buffer[] = []; |  | ||||||
|     req.on("data", d => data.push(d)); |  | ||||||
|     await new Promise((done, reject) => req.on("error", reject).once("close", () => { |  | ||||||
|       try { |  | ||||||
|         req.body = yaml.parse(Buffer.concat(data).toString("utf8")); |  | ||||||
|         done(null); |  | ||||||
|       } catch (err) { |  | ||||||
|         reject(err); |  | ||||||
|       } |  | ||||||
|     })); |  | ||||||
|   } |  | ||||||
|   next(); |  | ||||||
| }, express.json(), express.urlencoded({extended: true})); |  | ||||||
|  |  | ||||||
| // Get current server running |  | ||||||
| app.route("/v1").get(({res}) => res.json(Object.keys(sessions).reduce((acc, key) => { |  | ||||||
|   acc[key] = { |  | ||||||
|     ports: sessions[key].portListening, |  | ||||||
|     player: sessions[key].playerActions.reduce((acc, player) => { |  | ||||||
|       if (!acc[player.playerName]) acc[player.playerName] = player; |  | ||||||
|       else acc[player.playerName] = { |  | ||||||
|         ...player, |  | ||||||
|         previous: acc[player.playerName] |  | ||||||
|       }; |  | ||||||
|       return acc; |  | ||||||
|     }, {}) |  | ||||||
|   }; |  | ||||||
|   return acc; |  | ||||||
| }, {}))); |  | ||||||
|  |  | ||||||
| app.route("/v1/id").get(async ({res}) => res.json(await serverManeger.listIDs())).delete(async (req, res) => { |  | ||||||
|   const IDs: string[] = []; |  | ||||||
|   if (typeof req.body === "string") IDs.push(...(String(req.body).split(/[;,]/).map(s => s.trim()))) |  | ||||||
|   else if (Array.isArray(req.body)) IDs.push(...(req.body.map(k => typeof k === "string" ? k : k?.id).filter(s => !!s))) |  | ||||||
|  |  | ||||||
|   if (IDs.find(k => k === "*")) return Promise.all((await bdsCore.listIDs()).map(async (idManeger) => idManeger.delete().then(() => ({id: idManeger.id})).catch(err => ({err: String(err?.message || err)})))).then(res.json); |  | ||||||
|   else if (IDs.length > 0) { |  | ||||||
|     const folder = (await bdsCore.listIDs()).filter(k => IDs.includes(k.id)); |  | ||||||
|     if (folder.length === 0) return res.status(400).json({error: "all id is invalid"}); |  | ||||||
|     return Promise.all(folder.map(async (idManeger) => idManeger.delete().then(() => ({id: idManeger.id})).catch(err => ({err: String(err?.message || err)})))).then(res.json); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return res.status(400).json({ |  | ||||||
|     error: "Body is String or Array" |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| app.get("/v1/platform(s)?/:platform?", async (req, res) => { |  | ||||||
|   const { platform = "bedrock" } = req.params; |  | ||||||
|   if (!(platform === "bedrock"||platform === "java")) return res.status(400).json({error: "Invalid platform"}); |  | ||||||
|   if (platform === "bedrock") { |  | ||||||
|     return res.json(await bdsCore.Bedrock.listVersions(req.query.alt as any)); |  | ||||||
|   } |  | ||||||
|   return res.json(await bdsCore.Java.listVersions(req.query.alt as any)); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| app.route("/v1/server").put(async (req, res) => { |  | ||||||
|   const { platform } = req.body as { platform: "bedrock"|"java" }; |  | ||||||
|   if (!(platform === "bedrock" || platform === "java")) return res.status(400).json({error: "Platform is invalid"}); |  | ||||||
|   const platformInstall = await (platform === "java" ? bdsCore.Java.installServer : bdsCore.Bedrock.installServer)({ |  | ||||||
|     newID: true, |  | ||||||
|     version: req.body?.version ?? "latest", |  | ||||||
|     altServer: req.body?.altServer as never, |  | ||||||
|     allowBeta: req.body?.allowBeta ?? req.query.allowBeta === "true" |  | ||||||
|   }); |  | ||||||
|   delete platformInstall["downloads"]?.server?.urls; |  | ||||||
|   return res.json(platformInstall); |  | ||||||
| }).patch(async (req, res) => { |  | ||||||
|   const { id } = req.body; |  | ||||||
|   const localID = (await bdsCore.listIDs()).find(ind => ind.id === id); |  | ||||||
|   if (!localID) return res.status(400).json({error: "server not installed to update"}); |  | ||||||
|   if (sessions[id]) await sessions[id].stopServer(); |  | ||||||
|   const platformInstall = await (localID.platform === "java" ? bdsCore.Java.installServer : bdsCore.Bedrock.installServer)({ |  | ||||||
|     newID: true, |  | ||||||
|     version: req.body?.version ?? "latest", |  | ||||||
|     altServer: req.body?.altServer as never, |  | ||||||
|     allowBeta: req.body?.allowBeta ?? req.query.allowBeta === "true" |  | ||||||
|   }); |  | ||||||
|   delete platformInstall["downloads"]?.server?.urls; |  | ||||||
|   return res.json(platformInstall); |  | ||||||
| }).post(async (req, res) => { |  | ||||||
|   const { id } = req.body; |  | ||||||
|   const idInfo = (await serverManeger.listIDs()).find(f => f.id === id); |  | ||||||
|   if (!idInfo) return res.status(400).json({error: "ID not exsists"}); |  | ||||||
|   if (sessions[id]) return res.status(400).json({error: "Server are running"}); |  | ||||||
|   sessions[id] = await (idInfo.platform === "java" ? bdsCore.Java.startServer : bdsCore.Bedrock.startServer)({ |  | ||||||
|     newID: false, |  | ||||||
|     ID: id |  | ||||||
|   }); |  | ||||||
|   sessions[id].once("close", () => delete sessions[id]).on("line", (line, from) => console.log("[%s from %s]: %s", id, from, line)); |  | ||||||
|   return res.json({ |  | ||||||
|     spawnargs: sessions[id].spawnargs, |  | ||||||
|     pid: sessions[id].pid, |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| app.route("/v1/server/:id").get((req, res) => { |  | ||||||
|   if (!sessions[req.params.id]) return res.status(400).json({error: "Session not running"}); |  | ||||||
|   return res.json({ |  | ||||||
|     // bedrockConnect: sessions[req.params.id].runOptions.paths.platform === "java" ? null : `minecraft:?addExternalServer=${sessions[req.params.id].runOptions.paths.id}|${}:${sessions[req.params.id].portListening.at(0).port}`, |  | ||||||
|     ports: sessions[req.params.id].portListening, |  | ||||||
|     player: sessions[req.params.id].playerActions.reduce((acc, player) => { |  | ||||||
|       if (!acc[player.playerName]) acc[player.playerName] = player; |  | ||||||
|       else acc[player.playerName] = { |  | ||||||
|         ...player, |  | ||||||
|         previous: acc[player.playerName] |  | ||||||
|       }; |  | ||||||
|       return acc; |  | ||||||
|     }, {}) |  | ||||||
|   }); |  | ||||||
| }).post(async (req, res) => { |  | ||||||
|   if (!sessions[req.params.id]) return res.status(400).json({error: "Session not running"}); |  | ||||||
|   if (Array.isArray(req.body)) sessions[req.params.id].sendCommand(...req.body); |  | ||||||
|   else sessions[req.params.id].sendCommand(req); |  | ||||||
|   return res.status(200).send("ok"); |  | ||||||
| }).delete((req, res) => { |  | ||||||
|   if (!sessions[req.params.id]) return res.status(400).json({error: "Session not running"}); |  | ||||||
|   return sessions[req.params.id].stopServer().then(res.json).catch(err => res.status(400).json({err: String(err?.message || err)})); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // Listen |  | ||||||
| app.listen(process.env.PORT ?? 3000, function() {const a = this.address(); console.log("Bds API Listen on %O", a?.["port"] ?? a)}); |  | ||||||
| @@ -1,4 +0,0 @@ | |||||||
| { |  | ||||||
|   "extends": "../../tsconfig.json", |  | ||||||
|   "references": [{"path": "../core"}] |  | ||||||
| } |  | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "bds-maneger", |   "name": "bds-maneger", | ||||||
|   "version": "6.0.1", |   "version": "6.0.4", | ||||||
|   "description": "", |   "description": "", | ||||||
|   "main": "src/index.js", |   "main": "src/index.js", | ||||||
|   "type": "module", |   "type": "module", | ||||||
| @@ -16,7 +16,7 @@ | |||||||
|   }, |   }, | ||||||
|   "keywords": [], |   "keywords": [], | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@the-bds-maneger/core": "^6.0.3", |     "@the-bds-maneger/core": "^6.0.4", | ||||||
|     "yargs": "^17.7.2" |     "yargs": "^17.7.2" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
| @@ -39,12 +39,15 @@ yargs(process.argv.slice(2)).version(false).help(true).strictCommands().demandCo | |||||||
|   }) |   }) | ||||||
|   .parseSync(); |   .parseSync(); | ||||||
| 
 | 
 | ||||||
|   const installData = await (options.platform === "java" ? bdsCore.Java.installServer : bdsCore.Bedrock.installServer)({ |   const serverPath = await bdsCore.serverManeger.serverManeger(options.platform === "java" ? "java" : "bedrock", { | ||||||
|     ...(options.id ? {newID: false, ID: options.id} : {newID: true}), |     ...(options.id ? {newID: false, ID: options.id} : {newID: true}), | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   const installData = await (options.platform === "java" ? bdsCore.Java.installServer : bdsCore.Bedrock.installServer)(Object.assign({}, serverPath, { | ||||||
|     version: options.version, |     version: options.version, | ||||||
|     altServer: options.altserver as never, |     altServer: options.altserver as never, | ||||||
|     allowBeta: Boolean(options.beta) |     allowBeta: Boolean(options.beta) | ||||||
|   }); |   })); | ||||||
| 
 | 
 | ||||||
|   console.log("ID: %O, Server Version: %O, Server Date: %O", installData.id, installData.version, installData.date); |   console.log("ID: %O, Server Version: %O, Server Date: %O", installData.id, installData.version, installData.date); | ||||||
| }) | }) | ||||||
| @@ -73,7 +76,8 @@ yargs(process.argv.slice(2)).version(false).help(true).strictCommands().demandCo | |||||||
|   }).parseSync(); |   }).parseSync(); | ||||||
|   const idInfo = (await bdsCore.listIDs()).find(local => local.id === option.id); |   const idInfo = (await bdsCore.listIDs()).find(local => local.id === option.id); | ||||||
|   if (!idInfo) throw new Error("Invalid ID"); |   if (!idInfo) throw new Error("Invalid ID"); | ||||||
|   const session = await (idInfo.platform === "java" ? bdsCore.Java.startServer : bdsCore.Bedrock.startServer)({ID: idInfo.id}); |   const sserverPaths = await bdsCore.serverManeger.serverManeger(option.platform === "java" ? "java" : "bedrock", {ID: option.id, newID: false}); | ||||||
|  |   const session = await (idInfo.platform === "java" ? bdsCore.Java.startServer : bdsCore.Bedrock.startServer)(sserverPaths); | ||||||
|   process.on("error", console.log); |   process.on("error", console.log); | ||||||
|   session.once("backup", filePath => console.log("Backup file path: %O", filePath)); |   session.once("backup", filePath => console.log("Backup file path: %O", filePath)); | ||||||
|   process.stdin.pipe(session.stdin); |   process.stdin.pipe(session.stdin); | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "@the-bds-maneger/core", |   "name": "@the-bds-maneger/core", | ||||||
|   "version": "6.0.1", |   "version": "6.0.4", | ||||||
|   "description": "", |   "description": "", | ||||||
|   "main": "src/index.js", |   "main": "src/index.js", | ||||||
|   "types": "src/index.d.ts", |   "types": "src/index.d.ts", | ||||||
| @@ -20,13 +20,15 @@ | |||||||
|     "@sirherobrine23/extends": "^3.6.11", |     "@sirherobrine23/extends": "^3.6.11", | ||||||
|     "@sirherobrine23/http": "^3.6.11", |     "@sirherobrine23/http": "^3.6.11", | ||||||
|     "sanitize-filename": "^1.6.3", |     "sanitize-filename": "^1.6.3", | ||||||
|     "semver": "^7.5.0", |     "semver": "^7.5.1", | ||||||
|     "tar": "^6.1.14", |     "tar": "^6.1.15", | ||||||
|     "unzip-stream": "^0.3.1" |     "unzip-stream": "^0.3.1", | ||||||
|  |     "unzipper": "^0.10.14" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@types/semver": "^7.5.0", |     "@types/semver": "^7.5.0", | ||||||
|     "@types/tar": "^6.1.5", |     "@types/tar": "^6.1.5", | ||||||
|     "@types/unzip-stream": "^0.3.1" |     "@types/unzip-stream": "^0.3.1", | ||||||
|  |     "@types/unzipper": "^0.10.6" | ||||||
|   } |   } | ||||||
| } | } | ||||||
							
								
								
									
										2
									
								
								packages/core/src/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								packages/core/src/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | export * from "./reindex.js"; | ||||||
|  | export * as default from "./reindex.js"; | ||||||
							
								
								
									
										4
									
								
								packages/core/src/reindex.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								packages/core/src/reindex.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | export * from "./serverManeger.js"; | ||||||
|  | export * as serverManeger from "./serverManeger.js"; | ||||||
|  | export * as Bedrock from "./servers/bedrock.js"; | ||||||
|  | export * as Java from "./servers/java.js"; | ||||||
| @@ -19,15 +19,15 @@ export const bdsManegerRoot = ENVROOT ? path.resolve(process.cwd(), ENVROOT) : p | |||||||
| if (!(await extendsFS.exists(bdsManegerRoot))) await fs.mkdir(bdsManegerRoot, {recursive: true}); | if (!(await extendsFS.exists(bdsManegerRoot))) await fs.mkdir(bdsManegerRoot, {recursive: true}); | ||||||
| export type withPromise<T> = T|Promise<T>; | export type withPromise<T> = T|Promise<T>; | ||||||
| 
 | 
 | ||||||
| export type manegerOptions = { | export interface manegerOptions { | ||||||
|   ID?: string, |   ID?: string, | ||||||
|   newID?: boolean, |   newID?: boolean, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // only letters and numbers
 | // only letters and numbers
 | ||||||
| const idReg = /^[a-zA-Z0-9]+$/; | const idReg = /^[a-zA-Z0-9_]+$/; | ||||||
| 
 | 
 | ||||||
| export type serverManegerV1 = { | export interface serverManegerV1 { | ||||||
|   id: string, |   id: string, | ||||||
|   rootPath: string, |   rootPath: string, | ||||||
|   serverFolder: string, |   serverFolder: string, | ||||||
| @@ -49,7 +49,7 @@ export async function serverManeger(platform: serverManegerV1["platform"], optio | |||||||
|   // Create or check if exists
 |   // Create or check if exists
 | ||||||
|   if (options.newID === true) { |   if (options.newID === true) { | ||||||
|     while(true) { |     while(true) { | ||||||
|       options.ID = crypto.randomBytes(crypto.randomInt(8, 14)).toString("hex"); |       options.ID = typeof crypto.randomUUID === "function" ?  crypto.randomUUID().split("-").join("_") : crypto.randomBytes(crypto.randomInt(8, 14)).toString("hex"); | ||||||
|       if (!(idReg.test(options.ID))) continue; |       if (!(idReg.test(options.ID))) continue; | ||||||
|       if (!((await fs.readdir(platformFolder).catch(() => [])).includes(options.ID))) break; |       if (!((await fs.readdir(platformFolder).catch(() => [])).includes(options.ID))) break; | ||||||
|     } |     } | ||||||
| @@ -171,7 +171,7 @@ export declare class serverRun extends child_process.ChildProcess { | |||||||
|   avaibleDate?: Date; |   avaibleDate?: Date; | ||||||
|   runOptions: runOptions; |   runOptions: runOptions; | ||||||
|   portListening: portListen[]; |   portListening: portListen[]; | ||||||
|   logPath: {stderr: string, stdout: string}; |   logPath: {stderr: string, stdout: string, merged: string}; | ||||||
|   playerActions: playerAction[]; |   playerActions: playerAction[]; | ||||||
|   stdoutInterface: readline.Interface; |   stdoutInterface: readline.Interface; | ||||||
|   stderrInterface: readline.Interface; |   stderrInterface: readline.Interface; | ||||||
| @@ -186,6 +186,7 @@ export declare class serverRun extends child_process.ChildProcess { | |||||||
|  * Run servers globally and hormonally across servers |  * Run servers globally and hormonally across servers | ||||||
|  */ |  */ | ||||||
| export async function runServer(options: runOptions): Promise<serverRun> { | export async function runServer(options: runOptions): Promise<serverRun> { | ||||||
|  |   if (!options.stdio) options.stdio = ["pipe", "pipe", "pipe"]; | ||||||
|   const child = child_process.spawn(options.command, [...((options.args ?? []).map(String))], { |   const child = child_process.spawn(options.command, [...((options.args ?? []).map(String))], { | ||||||
|     // maxBuffer: Infinity,
 |     // maxBuffer: Infinity,
 | ||||||
|     stdio: options.stdio, |     stdio: options.stdio, | ||||||
| @@ -210,8 +211,11 @@ export async function runServer(options: runOptions): Promise<serverRun> { | |||||||
|   const currentDate = new Date(); |   const currentDate = new Date(); | ||||||
|   const baseLog = path.join(options.paths.logs, format("%s_%s_%s_%s-%s-%s", currentDate.getDate(), currentDate.getMonth()+1, currentDate.getFullYear(), currentDate.getHours(), currentDate.getMinutes(), currentDate.getSeconds())); |   const baseLog = path.join(options.paths.logs, format("%s_%s_%s_%s-%s-%s", currentDate.getDate(), currentDate.getMonth()+1, currentDate.getFullYear(), currentDate.getHours(), currentDate.getMinutes(), currentDate.getSeconds())); | ||||||
|   await fs.mkdir(baseLog, {recursive: true}); |   await fs.mkdir(baseLog, {recursive: true}); | ||||||
|   child.logPath = {stdout: path.join(baseLog, "stdout.log"), stderr: path.join(baseLog, "stderr.log")}; |   child.logPath = {stdout: path.join(baseLog, "stdout.log"), stderr: path.join(baseLog, "stderr.log"), merged: path.join(baseLog, "server.log")}; | ||||||
|  |   const allLog = createWriteStream(child.logPath.merged); | ||||||
|  |   child.stdout.pipe(allLog); | ||||||
|   child.stdout.pipe(createWriteStream(child.logPath.stdout)); |   child.stdout.pipe(createWriteStream(child.logPath.stdout)); | ||||||
|  |   child.stderr.pipe(allLog); | ||||||
|   child.stderr.pipe(createWriteStream(child.logPath.stderr)); |   child.stderr.pipe(createWriteStream(child.logPath.stderr)); | ||||||
| 
 | 
 | ||||||
|   // Lines
 |   // Lines
 | ||||||
| @@ -265,7 +269,7 @@ export async function runServer(options: runOptions): Promise<serverRun> { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   child.hotBackup = function hotBackup() { |   child.hotBackup = function hotBackup() { | ||||||
|     return Object.assign(Promise.resolve().then((async () => { |     return Object.assign({}, Promise.resolve().then((async () => { | ||||||
|       if (!options.serverActions?.hotBackup) throw new Error("Hot backup disabled to current platform!"); |       if (!options.serverActions?.hotBackup) throw new Error("Hot backup disabled to current platform!"); | ||||||
|       child.emit("backup", "start"); |       child.emit("backup", "start"); | ||||||
|       return Promise.resolve(options.serverActions.hotBackup.call(child) as ReturnType<typeof options.serverActions.hotBackup>).then(data => { |       return Promise.resolve(options.serverActions.hotBackup.call(child) as ReturnType<typeof options.serverActions.hotBackup>).then(data => { | ||||||
| @@ -1,21 +1,21 @@ | |||||||
| import fsOld, { promises as fs } from "node:fs"; | import fsOld, { promises as fs } from "node:fs"; | ||||||
| import coreHttp, { Github } from "@sirherobrine23/http"; | import coreHttp, { Github } from "@sirherobrine23/http"; | ||||||
| import { manegerOptions, runOptions, serverManeger, serverManegerV1 } from "../serverManeger.js"; | import { runOptions, serverManegerV1 } from "../serverManeger.js"; | ||||||
| import { oracleStorage } from "../internal.js"; | import { oracleStorage } from "../internal.js"; | ||||||
| import { pipeline } from "node:stream/promises"; | import { pipeline } from "node:stream/promises"; | ||||||
| import { Readable } from "node:stream"; | import { Readable } from "node:stream"; | ||||||
| import extendsFS, { promiseChildProcess } from "@sirherobrine23/extends"; | import extendsFS, { promiseChildProcess } from "@sirherobrine23/extends"; | ||||||
| import semver from "semver"; | import semver from "semver"; | ||||||
| import unzip from "unzip-stream"; | import unzip from "unzipper"; | ||||||
| import utils from "node:util"; | import utils from "node:util"; | ||||||
| import path from "node:path"; | import path from "node:path"; | ||||||
| import tar from "tar"; | import tar from "tar"; | ||||||
| 
 | 
 | ||||||
| export type bedrockOptions = manegerOptions & { | export interface bedrockOptions { | ||||||
|   /** |   /** | ||||||
|    * Alternative server instead of official Mojang server |    * Alternative server instead of official Mojang server | ||||||
|    */ |    */ | ||||||
|   altServer?: "pocketmine"|"powernukkit"|"nukkit"|"cloudbust", |   altServer?: "mojang"|"pocketmine"|"powernukkit"|"nukkit"|"cloudbust", | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const pocketmineGithub = await Github.repositoryManeger("pmmp", "PocketMine-MP"); | const pocketmineGithub = await Github.repositoryManeger("pmmp", "PocketMine-MP"); | ||||||
| @@ -47,7 +47,8 @@ export type bedrockList = { | |||||||
|  * @returns |  * @returns | ||||||
|  */ |  */ | ||||||
| export async function listVersions(altServer?: bedrockOptions["altServer"]): Promise<bedrockList[]> { | export async function listVersions(altServer?: bedrockOptions["altServer"]): Promise<bedrockList[]> { | ||||||
|   if (altServer) if (!(["cloudbust", "cloudbust", "nukkit", "pocketmine", "powernukkit"]).includes(altServer)) throw new TypeError("Invalid alt server"); |   if (!altServer) altServer = "mojang"; | ||||||
|  |   if (altServer) if (!(["mojang", "cloudbust", "cloudbust", "nukkit", "pocketmine", "powernukkit"]).includes(altServer)) throw new TypeError("Invalid alt server"); | ||||||
|   if (altServer === "pocketmine") { |   if (altServer === "pocketmine") { | ||||||
|     return (await pocketmineGithub.release.getRelease()).filter(rel => (rel.assets.find(assert => assert.name.endsWith(".phar")) ?? {}).browser_download_url).map(rel => ({ |     return (await pocketmineGithub.release.getRelease()).filter(rel => (rel.assets.find(assert => assert.name.endsWith(".phar")) ?? {}).browser_download_url).map(rel => ({ | ||||||
|       date: new Date(rel.created_at), |       date: new Date(rel.created_at), | ||||||
| @@ -137,30 +138,32 @@ export async function listVersions(altServer?: bedrockOptions["altServer"]): Pro | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     })); |     })); | ||||||
|   } |   } else if (altServer === "mojang") { | ||||||
|   return (await coreHttp.jsonRequest<{version: string, date: Date, release?: "stable"|"preview", url: {[platform in NodeJS.Platform]?: {[arch in NodeJS.Architecture]?: string}}}[]>("https://sirherobrine23.github.io/BedrockFetch/all.json")).body.sort((b, a) => semver.compare(semver.valid(semver.coerce(a.version)), semver.valid(semver.coerce(b.version)))).map(rel => ({ | 
 | ||||||
|     version: rel.version, |     return (await coreHttp.jsonRequest<{version: string, date: Date, release?: "stable"|"preview", url: {[platform in NodeJS.Platform]?: {[arch in NodeJS.Architecture]?: string}}}[]>("https://sirherobrine23.github.io/BedrockFetch/all.json")).body.sort((b, a) => semver.compare(semver.valid(semver.coerce(a.version)), semver.valid(semver.coerce(b.version)))).map(rel => ({ | ||||||
|     date: new Date(rel.date), |       version: rel.version, | ||||||
|     release: rel.release === "preview" ? "preview" : "stable", |       date: new Date(rel.date), | ||||||
|     downloads: { |       release: rel.release === "preview" ? "preview" : "stable", | ||||||
|       server: { |       downloads: { | ||||||
|         url: rel.url[process.platform]?.[process.arch], |         server: { | ||||||
|         async getServer() { |           url: rel.url[process.platform]?.[process.arch], | ||||||
|           const platformURL = (rel.url[process.platform] ?? rel.url["linux"]); |           async getServer() { | ||||||
|           if (!platformURL) throw new Error("Cannot get platform URL"); |             const platformURL = (rel.url[process.platform] ?? rel.url["linux"]); | ||||||
|           const arch = platformURL[process.arch] ?? platformURL["x64"]; |             if (!platformURL) throw new Error("Cannot get platform URL"); | ||||||
|           if (!arch) throw new Error("Cannot get bedrock server to current arch"); |             const arch = platformURL[process.arch] ?? platformURL["x64"]; | ||||||
|           return coreHttp.streamRequest(arch); |             if (!arch) throw new Error("Cannot get bedrock server to current arch"); | ||||||
|         }, |             return coreHttp.streamRequest(arch); | ||||||
|         urls: rel.url |           }, | ||||||
|  |           urls: rel.url | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     })); | ||||||
|   })); |   } else throw new Error("Invalid platform"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function installServer(options: bedrockOptions & {version?: string, allowBeta?: boolean}) { | export async function installServer(serverPath: serverManegerV1, options: bedrockOptions & {version?: string, allowBeta?: boolean}) { | ||||||
|   const serverPath = await serverManeger("bedrock", options); |  | ||||||
|   const versions = await listVersions(options?.altServer); |   const versions = await listVersions(options?.altServer); | ||||||
|  |   if (!options.altServer) options.altServer = "mojang"; | ||||||
|   if (options.altServer === "pocketmine") { |   if (options.altServer === "pocketmine") { | ||||||
|     const rel = options.version === "latest" ? versions.at(0) : versions.find(rel => rel.version === options.version); |     const rel = options.version === "latest" ? versions.at(0) : versions.find(rel => rel.version === options.version); | ||||||
|     if (!rel) throw new Error("Version not exsists"); |     if (!rel) throw new Error("Version not exsists"); | ||||||
| @@ -179,39 +182,40 @@ export async function installServer(options: bedrockOptions & {version?: string, | |||||||
|       ...rel, |       ...rel, | ||||||
|       id: serverPath.id, |       id: serverPath.id, | ||||||
|     }; |     }; | ||||||
|   } |   } else if (options.altServer === "mojang") { | ||||||
|   const bedrockVersion = versions.find(rel => { |     const bedrockVersion = versions.find(rel => { | ||||||
|     if (rel.release === "preview") if (options.allowBeta !== true) return false; |       if (rel.release === "preview") if (options.allowBeta !== true) return false; | ||||||
|     const version = (options.version ?? "latest").trim(); |       const version = (options.version ?? "latest").trim(); | ||||||
|     if (version.toLowerCase() === "latest") return true; |       if (version.toLowerCase() === "latest") return true; | ||||||
|     return rel.version === version; |       return rel.version === version; | ||||||
|   }); |     }); | ||||||
|   if (!bedrockVersion) throw new Error("Não existe essa versão"); |     if (!bedrockVersion) throw new Error("Não existe essa versão"); | ||||||
|   let downloadUrl = bedrockVersion.downloads.server.url; |     let downloadUrl = bedrockVersion.downloads.server.url; | ||||||
|   if ((["android", "linux"] as NodeJS.Process["platform"][]).includes(process.platform) && process.arch !== "x64") { |     if ((["android", "linux"] as NodeJS.Process["platform"][]).includes(process.platform) && process.arch !== "x64") { | ||||||
|     if (!downloadUrl) { |       if (!downloadUrl) { | ||||||
|       for (const emu of ["qemu-x86_64-static", "qemu-x86_64", "box64"]) { |         for (const emu of ["qemu-x86_64-static", "qemu-x86_64", "box64"]) { | ||||||
|         if (downloadUrl) break; |           if (downloadUrl) break; | ||||||
|         if (await promiseChildProcess.commandExists(emu)) downloadUrl = bedrockVersion.downloads.server.urls.linux?.x64; |           if (await promiseChildProcess.commandExists(emu)) downloadUrl = bedrockVersion.downloads.server.urls.linux?.x64; | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |     if (!downloadUrl) throw new Error(`Não existe o URL de download para ${process.platform} na arquitetura ${process.arch}`); | ||||||
|   if (!downloadUrl) throw new Error(`Não existe o URL de download para ${process.platform} na arquitetura ${process.arch}`); |  | ||||||
| 
 | 
 | ||||||
|   const filesBackup = ["server.properties", "valid_known_packs.json", "permissions.json", "allowlist.json", "whitelist.json"]; |     const filesBackup = ["server.properties", "valid_known_packs.json", "permissions.json", "allowlist.json", "whitelist.json"]; | ||||||
|   const datS = (await Promise.all(filesBackup.map(async f => !await extendsFS.exists(path.join(serverPath.serverFolder, f)) ? null : ({path: f, data: await fs.readFile(path.join(serverPath.serverFolder, f))})))).filter(a => !!a); |     const datS = (await Promise.all(filesBackup.map(async f => !await extendsFS.exists(path.join(serverPath.serverFolder, f)) ? null : ({path: f, data: await fs.readFile(path.join(serverPath.serverFolder, f))})))).filter(a => !!a); | ||||||
|   await pipeline(await coreHttp.streamRequest(downloadUrl), unzip.Extract({path: serverPath.serverFolder})); |     await pipeline(await coreHttp.streamRequest(downloadUrl), unzip.Extract({path: serverPath.serverFolder})); | ||||||
|   await Promise.all(datS.map(async f => fs.writeFile(f.path, f.data))); |     await Promise.all(datS.map(async f => fs.writeFile(f.path, f.data))); | ||||||
|   return { |     return { | ||||||
|     ...bedrockVersion, |       ...bedrockVersion, | ||||||
|     id: serverPath.id, |       id: serverPath.id, | ||||||
|   }; |     }; | ||||||
|  |   } else throw new Error("Invalid platform"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function startServer(options: bedrockOptions) { | export async function startServer(maneger: serverManegerV1, options: bedrockOptions) { | ||||||
|   const serverPath = await serverManeger("bedrock", options); |   if (!options.altServer) options.altServer = "mojang"; | ||||||
|   if (options.altServer === "powernukkit"||options.altServer === "cloudbust") { |   if (options.altServer === "powernukkit"||options.altServer === "cloudbust") { | ||||||
|     return serverPath.runCommand({ |     return maneger.runCommand({ | ||||||
|       command: "java", |       command: "java", | ||||||
|       args: [ |       args: [ | ||||||
|         "-XX:+UseG1GC", |         "-XX:+UseG1GC", | ||||||
| @@ -236,7 +240,7 @@ export async function startServer(options: bedrockOptions) { | |||||||
|         "-Daikars.new.flags=true", |         "-Daikars.new.flags=true", | ||||||
|         "-jar", "server.jar", |         "-jar", "server.jar", | ||||||
|       ], |       ], | ||||||
|       paths: serverPath, |       paths: maneger, | ||||||
|       serverActions: { |       serverActions: { | ||||||
|         stop() { |         stop() { | ||||||
|           this.sendCommand("stop"); |           this.sendCommand("stop"); | ||||||
| @@ -244,13 +248,13 @@ export async function startServer(options: bedrockOptions) { | |||||||
|       } |       } | ||||||
|     }) |     }) | ||||||
|   } else if (options.altServer === "pocketmine") { |   } else if (options.altServer === "pocketmine") { | ||||||
|     return serverPath.runCommand({ |     return maneger.runCommand({ | ||||||
|       command: (await extendsFS.readdir(serverPath.serverFolder)).find(file => file.endsWith("php")||file.endsWith("php.exe")), |       command: (await extendsFS.readdir(maneger.serverFolder)).find(file => file.endsWith("php")||file.endsWith("php.exe")), | ||||||
|       args: [ |       args: [ | ||||||
|         "server.phar", |         "server.phar", | ||||||
|         "--no-wizard" |         "--no-wizard" | ||||||
|       ], |       ], | ||||||
|       paths: serverPath, |       paths: maneger, | ||||||
|       serverActions: { |       serverActions: { | ||||||
|         stop() { |         stop() { | ||||||
|           this.sendCommand("stop") |           this.sendCommand("stop") | ||||||
| @@ -260,8 +264,8 @@ export async function startServer(options: bedrockOptions) { | |||||||
|   } |   } | ||||||
|   if (process.platform === "darwin") throw new Error("Run in docker or podman!"); |   if (process.platform === "darwin") throw new Error("Run in docker or podman!"); | ||||||
|   const run: Omit<runOptions, "cwd"> = { |   const run: Omit<runOptions, "cwd"> = { | ||||||
|     command: path.join(serverPath.serverFolder, "bedrock_server"), |     command: path.join(maneger.serverFolder, "bedrock_server"+(process.platform === "win32" ? ".exe" : "")), | ||||||
|     paths: serverPath, |     paths: maneger, | ||||||
|     serverActions: { |     serverActions: { | ||||||
|       stop() { |       stop() { | ||||||
|         this.sendCommand("stop"); |         this.sendCommand("stop"); | ||||||
| @@ -322,6 +326,19 @@ export async function startServer(options: bedrockOptions) { | |||||||
|         if (data.includes("started") && data.includes("Server")) return new Date(); |         if (data.includes("started") && data.includes("Server")) return new Date(); | ||||||
|         return null |         return null | ||||||
|       }, |       }, | ||||||
|  |       async hotBackup() { | ||||||
|  |         const ff = (await fs.readdir(this.runOptions.paths.serverFolder)).filter(ff => { | ||||||
|  |           let ok = ff.endsWith(".json"); | ||||||
|  |           if (!ok) ok = ff === "server.properties"; | ||||||
|  |           if (!ok) ok = ff === "worlds"; | ||||||
|  |           return ok; | ||||||
|  |         }); | ||||||
|  |         return tar.create({ | ||||||
|  |           gzip: true, | ||||||
|  |           cwd: this.runOptions.paths.serverFolder, | ||||||
|  |           prefix: "" | ||||||
|  |         }, ff); | ||||||
|  |       }, | ||||||
|       postStart: [ |       postStart: [ | ||||||
|         async function() { |         async function() { | ||||||
|           let breaked = false; |           let breaked = false; | ||||||
| @@ -367,5 +384,5 @@ export async function startServer(options: bedrockOptions) { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   return serverPath.runCommand(run); |   return maneger.runCommand(run); | ||||||
| } | } | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { manegerOptions, serverManeger } from "../serverManeger.js"; | import { serverManegerV1 } from "../serverManeger.js"; | ||||||
| import { oracleStorage } from "../internal.js"; | import { oracleStorage } from "../internal.js"; | ||||||
| import { extendsFS } from "@sirherobrine23/extends"; | import { extendsFS } from "@sirherobrine23/extends"; | ||||||
| import { pipeline } from "node:stream/promises"; | import { pipeline } from "node:stream/promises"; | ||||||
| @@ -9,11 +9,11 @@ import utils from "node:util"; | |||||||
| import path from "node:path"; | import path from "node:path"; | ||||||
| import fs from "node:fs"; | import fs from "node:fs"; | ||||||
| 
 | 
 | ||||||
| export type javaOptions = manegerOptions & { | export interface javaOptions { | ||||||
|   /** |   /** | ||||||
|    * Alternative server instead of official Mojang server |    * Alternative server instead of official Mojang server | ||||||
|    */ |    */ | ||||||
|   altServer?: "spigot"|"paper"|"purpur"|"glowstone"|"folia"|"cuberite" |   altServer?: "mojang"|"spigot"|"paper"|"purpur"|"glowstone"|"folia"|"cuberite" | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export type javaList = { | export type javaList = { | ||||||
| @@ -30,7 +30,8 @@ export type javaList = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export async function listVersions(altServer?: javaOptions["altServer"]): Promise<javaList[]> { | export async function listVersions(altServer?: javaOptions["altServer"]): Promise<javaList[]> { | ||||||
|   if (altServer) if(!(["paper", "folia", "purpur", "spigot", "glowstone", "cuberite"]).includes(altServer)) throw new TypeError("Invalid alt server!"); |   if (!altServer) altServer = "mojang"; | ||||||
|  |   if (altServer) if(!(["mojang", "paper", "folia", "purpur", "spigot", "glowstone", "cuberite"]).includes(altServer)) throw new TypeError("Invalid alt server!"); | ||||||
|   if (altServer === "purpur") { |   if (altServer === "purpur") { | ||||||
|     return (await Promise.all((await coreHttp.jsonRequest<{versions: string[]}>("https://api.purpurmc.org/v2/purpur")).body.versions.map(async (version): Promise<javaList> => ({ |     return (await Promise.all((await coreHttp.jsonRequest<{versions: string[]}>("https://api.purpurmc.org/v2/purpur")).body.versions.map(async (version): Promise<javaList> => ({ | ||||||
|       version, |       version, | ||||||
| @@ -143,27 +144,27 @@ export async function listVersions(altServer?: javaOptions["altServer"]): Promis | |||||||
|         }, |         }, | ||||||
|       }] |       }] | ||||||
|     })); |     })); | ||||||
|   } |   } else if (altServer === "mojang") { | ||||||
| 
 |     return (await Promise.all((await coreHttp.jsonRequest<{versions: {id: string, releaseTime: string, url: string, type: "snapshot"|"release"}[]}>("https://launchermeta.mojang.com/mc/game/version_manifest_v2.json")).body.versions.map(async (data): Promise<javaList> => { | ||||||
|   return (await Promise.all((await coreHttp.jsonRequest<{versions: {id: string, releaseTime: string, url: string, type: "snapshot"|"release"}[]}>("https://launchermeta.mojang.com/mc/game/version_manifest_v2.json")).body.versions.map(async (data): Promise<javaList> => { |       const fileURL = (await coreHttp.jsonRequest<{downloads: {[k: string]: {size: number, url: string}}}>(data.url)).body.downloads?.["server"]?.url; | ||||||
|     const fileURL = (await coreHttp.jsonRequest<{downloads: {[k: string]: {size: number, url: string}}}>(data.url)).body.downloads?.["server"]?.url; |       if (!fileURL) return null; | ||||||
|     if (!fileURL) return null; |       return { | ||||||
|     return { |         version: data.id, | ||||||
|       version: data.id, |         date: new Date(data.releaseTime), | ||||||
|       date: new Date(data.releaseTime), |         release: data.type === "snapshot" ? "snapshot" : "stable", | ||||||
|       release: data.type === "snapshot" ? "snapshot" : "stable", |         getFile: [{ | ||||||
|       getFile: [{ |           fileName: "server.jar", | ||||||
|         fileName: "server.jar", |           async stream() { | ||||||
|         async stream() { |             return coreHttp.streamRequest(fileURL); | ||||||
|           return coreHttp.streamRequest(fileURL); |           }, | ||||||
|         }, |         }], | ||||||
|       }], |       }; | ||||||
|     }; |     }))).filter(a => !!a); | ||||||
|   }))).filter(a => !!a); |   } else throw new Error("Invalid platform"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function installServer(options: javaOptions & {version?: string, allowBeta?: boolean}) { | export async function installServer(serverPath: serverManegerV1, options: javaOptions & {version?: string, allowBeta?: boolean}) { | ||||||
|   const serverPath = await serverManeger("java", options); |   if (!options.altServer) options.altServer = "mojang"; | ||||||
|   const version = (await listVersions(options.altServer)).filter(rel => rel.release === "stable" ? true : !!options.allowBeta).find(rel => (!options.version || options.version === "latest" || rel.version === options.version)); |   const version = (await listVersions(options.altServer)).filter(rel => rel.release === "stable" ? true : !!options.allowBeta).find(rel => (!options.version || options.version === "latest" || rel.version === options.version)); | ||||||
|   if (!version) throw new Error("The specified version does not exist!"); |   if (!version) throw new Error("The specified version does not exist!"); | ||||||
|   for (const file of version.getFile) await pipeline(await file.stream(), fs.createWriteStream(path.join(serverPath.serverFolder, file.fileName))); |   for (const file of version.getFile) await pipeline(await file.stream(), fs.createWriteStream(path.join(serverPath.serverFolder, file.fileName))); | ||||||
| @@ -176,8 +177,8 @@ export async function installServer(options: javaOptions & {version?: string, al | |||||||
|   }; |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function startServer(options: javaOptions) { | export async function startServer(serverPath: serverManegerV1, options: javaOptions) { | ||||||
|   const serverPath = await serverManeger("java", options); |   if (!options.altServer) options.altServer = "mojang"; | ||||||
|   // Java server
 |   // Java server
 | ||||||
|   if (await extendsFS.exists(path.join(serverPath.serverFolder, "server.jar"))) { |   if (await extendsFS.exists(path.join(serverPath.serverFolder, "server.jar"))) { | ||||||
|     return serverPath.runCommand({ |     return serverPath.runCommand({ | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| { | { | ||||||
|   "name": "@the-bds-maneger/verapi", |   "name": "@the-bds-maneger/verapi", | ||||||
|   "private": true, |   "private": true, | ||||||
|   "version": "6.0.1", |   "version": "6.0.4", | ||||||
|   "description": "Public API to Minecraft Servers", |   "description": "Public API to Minecraft Servers", | ||||||
|   "main": "src/index.js", |   "main": "src/index.js", | ||||||
|   "type": "module", |   "type": "module", | ||||||
| @@ -16,10 +16,7 @@ | |||||||
|     "directory": "package/verapi" |     "directory": "package/verapi" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@the-bds-maneger/core": "^6.0.3", |     "@the-bds-maneger/core": "^6.0.4", | ||||||
|     "express": "^4.18.2" |     "express": "^4.18.2" | ||||||
|   }, |   } | ||||||
|   "workspaces": [ |  | ||||||
|     "../core" |  | ||||||
|   ] |  | ||||||
| } | } | ||||||
| @@ -20,7 +20,8 @@ | |||||||
|   }, |   }, | ||||||
|   "exclude": [ |   "exclude": [ | ||||||
|     "**/*.test.ts", |     "**/*.test.ts", | ||||||
|     "node_modules/" |     "**/node_modules/**", | ||||||
|  |     "packages/verapi/**" | ||||||
|   ], |   ], | ||||||
|   "ts-node": { |   "ts-node": { | ||||||
|     "files": true, |     "files": true, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user