Update actions and Bucket upload script #526
.github
.gitignore.npmignore.vscode
Dockerfilepackage.jsonpackage
packages
tsconfig.json
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