Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
f908be29b9 | |||
ccce234ae3 | |||
92153508b3 |
28
.gitignore
vendored
28
.gitignore
vendored
@ -1,2 +1,26 @@
|
|||||||
# NPM dependencies
|
# ---> Go
|
||||||
node_modules/
|
# If you prefer the allow list template instead of the deny list, see community template:
|
||||||
|
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||||
|
#
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it)
|
||||||
|
# vendor/
|
||||||
|
|
||||||
|
# Go workspace file
|
||||||
|
go.work
|
||||||
|
|
||||||
|
# Compiled Go binary
|
||||||
|
mcst
|
||||||
|
|
||||||
|
31
.woodpecker.yml
Normal file
31
.woodpecker.yml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
pipeline:
|
||||||
|
build_test:
|
||||||
|
image: golang:1.16
|
||||||
|
commands:
|
||||||
|
- go build
|
||||||
|
|
||||||
|
test:
|
||||||
|
image: golang:1.16
|
||||||
|
commands:
|
||||||
|
- go test -v ./...
|
||||||
|
|
||||||
|
build_release:
|
||||||
|
image: golang:1.16
|
||||||
|
commands:
|
||||||
|
- go mod vendor
|
||||||
|
- GOOS=linux GOARCH=amd64 go build -ldflags "-X git.metaunix.net/BitGoblin/mcst/cmd.version=${CI_COMMIT_TAG}" -o "dist/mcst-linux-amd64-${CI_COMMIT_TAG}"
|
||||||
|
- GOOS=windows GOARCH=amd64 go build -ldflags "-X git.metaunix.net/BitGoblin/mcst/cmd.version=${CI_COMMIT_TAG}" -o "dist/mcst-windows-amd64-${CI_COMMIT_TAG}.exe"
|
||||||
|
when:
|
||||||
|
event: tag
|
||||||
|
|
||||||
|
gitea_release:
|
||||||
|
image: plugins/gitea-release
|
||||||
|
settings:
|
||||||
|
api_key:
|
||||||
|
from_secret: gitea_api_key
|
||||||
|
base_url: https://git.metaunix.net
|
||||||
|
title: "${CI_COMMIT_TAG}"
|
||||||
|
files:
|
||||||
|
- dist/mcst-*
|
||||||
|
when:
|
||||||
|
event: tag
|
19
README.md
19
README.md
@ -1,3 +1,18 @@
|
|||||||
# mcst
|
# MCST
|
||||||
|
|
||||||
Bit Goblin minecraft server tool
|
Bit Goblin minecraft server management tool
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Build dependencies:
|
||||||
|
* go
|
||||||
|
* make
|
||||||
|
|
||||||
|
To install dependencies on Ubuntu: `apt install golang make`
|
||||||
|
To install dependencies on Red Hat/AlmaLinux: `dnf install go make`
|
||||||
|
|
||||||
|
To install MCST as a system utility: `make build && sudo make install`
|
||||||
|
|
||||||
|
## Uninstallation
|
||||||
|
|
||||||
|
To uninstall MCST (if it was installed through make): `sudo make uninstall`
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
const { exec } = require("child_process");
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
class Server {
|
|
||||||
constructor(dir) {
|
|
||||||
this.rootDir = dir;
|
|
||||||
this.name = dir.split('/').at(-1);
|
|
||||||
this.pidFilePath = this.rootDir + '/pid.txt';
|
|
||||||
|
|
||||||
// read version file
|
|
||||||
var versionFilePath = this.rootDir + '/current_version.txt';
|
|
||||||
if (fs.existsSync(versionFilePath)) {
|
|
||||||
this.version = fs.readFileSync(versionFilePath, {encoding:'utf8', flag:'r'});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
start() {
|
|
||||||
console.log(`Starting server ${this.name}...`);
|
|
||||||
|
|
||||||
// create shell command and execute it
|
|
||||||
let cmd = `${this.rootDir}/start.sh`;
|
|
||||||
exec(cmd, (err, stdout, stderr) => {
|
|
||||||
if (err) {
|
|
||||||
console.log(`Error while starting server: ${error.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Server ${this.name} has been started.`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
console.log(`Stopping server ${this.name}...`);
|
|
||||||
}
|
|
||||||
|
|
||||||
getStatus() {
|
|
||||||
if (fs.existsSync(this.pidFilePath)) {
|
|
||||||
let pid = fs.readFileSync(this.pidFilePath, {encoding: 'utf8', flag: 'r'});
|
|
||||||
try {
|
|
||||||
return process.kill(pid, 0);
|
|
||||||
} catch (err) {
|
|
||||||
// ESRCH error means the process doesn't exist, so should return false
|
|
||||||
if (err.code !== 'ESRCH') {
|
|
||||||
console.error(err);
|
|
||||||
return err.code === 'EPERM';
|
|
||||||
} else {
|
|
||||||
// delete pid.txt so we don't have to worry about checking it again
|
|
||||||
fs.unlinkSync(this.pidFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
getPid() {
|
|
||||||
if (fs.existsSync(this.pidFilePath)) {
|
|
||||||
return fs.readFileSync(this.pidFilePath, {encoding:'utf8', flag:'r'})
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.Server = Server;
|
|
92
cmd/new.go
Normal file
92
cmd/new.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"git.metaunix.net/BitGoblin/mcst/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
serverName string
|
||||||
|
minecraftVersion string
|
||||||
|
)
|
||||||
|
|
||||||
|
var newCmd = &cobra.Command{
|
||||||
|
Use: "new",
|
||||||
|
Short: "Create a new Minecraft server instance.",
|
||||||
|
Long: `Create a new Minecraft server instance.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
log.Printf("Creating new server with name '%s', and version '%s'\n", serverName, minecraftVersion)
|
||||||
|
|
||||||
|
serverDirectoryPath := util.ResolveTilde(fmt.Sprintf("~/%s", serverName))
|
||||||
|
|
||||||
|
err := os.Mkdir(serverDirectoryPath, 0755)
|
||||||
|
if err != nil && !os.IsExist(err) {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var serverJarURL string = "https://piston-data.mojang.com/v1/objects/f69c284232d7c7580bd89a5a4931c3581eae1378/server.jar"
|
||||||
|
var serverFilePath string = fmt.Sprintf("%s/server_%s.jar", serverDirectoryPath, minecraftVersion)
|
||||||
|
|
||||||
|
log.Printf("Downloading %s to %s\n", serverJarURL, serverFilePath)
|
||||||
|
file, err := os.Create(serverFilePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := http.Client{
|
||||||
|
CheckRedirect: func(r *http.Request, via []*http.Request) error {
|
||||||
|
r.URL.Opaque = r.URL.Path
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put content on file
|
||||||
|
resp, err := client.Get(serverJarURL)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(file, resp.Body)
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// create the shell script to start the server
|
||||||
|
log.Printf("Creating start.sh shell script.\n")
|
||||||
|
var scriptFilePath string = fmt.Sprintf("%s/start.sh", serverDirectoryPath)
|
||||||
|
scriptFile, err := os.Create(scriptFilePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to open file: %v", err)
|
||||||
|
}
|
||||||
|
defer scriptFile.Close()
|
||||||
|
|
||||||
|
// add text to the file
|
||||||
|
_, err = scriptFile.WriteString(fmt.Sprintf("#!/bin/sh\n\ncd %s\njava -Xmx2048M -Xms2048M -jar server_%s.jar nogui", serverDirectoryPath, minecraftVersion))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to write data: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set permissions on the script
|
||||||
|
err = os.Chmod(scriptFilePath, 0755)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to change script permissions: %v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// bind flags to variables
|
||||||
|
newCmd.Flags().StringVarP(&serverName, "server-name", "n", "", "The name for your new server.")
|
||||||
|
newCmd.MarkFlagRequired("server-name")
|
||||||
|
newCmd.Flags().StringVarP(&minecraftVersion, "minecraft-version", "m", "", "Minecraft Java Edition server version to use.")
|
||||||
|
newCmd.MarkFlagRequired("minecraft-version")
|
||||||
|
|
||||||
|
// add this command to the command root
|
||||||
|
rootCmd.AddCommand(newCmd)
|
||||||
|
}
|
30
cmd/root.go
Normal file
30
cmd/root.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
version string
|
||||||
|
)
|
||||||
|
|
||||||
|
var rootCmd = &cobra.Command{
|
||||||
|
Use: "mcst",
|
||||||
|
Short: "MCST is a tool to manage Minecraft Java edition servers.",
|
||||||
|
Long: `A flexible yet user-friendly tool to manage Minecraft Java edition server.
|
||||||
|
Source code available at https://git.metaunix.net/BitGoblin/mcst`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
log.Printf("This is a test.")
|
||||||
|
},
|
||||||
|
Version: version,
|
||||||
|
}
|
||||||
|
|
||||||
|
func Start() {
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"server_directory": "/opt/minecraft"
|
|
||||||
}
|
|
14
go.mod
Normal file
14
go.mod
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
module git.metaunix.net/BitGoblin/mcst
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/spf13/cobra v1.5.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/stretchr/objx v0.4.0 // indirect
|
||||||
|
github.com/stretchr/testify v1.8.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
24
go.sum
Normal file
24
go.sum
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||||
|
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
30
index.js
30
index.js
@ -1,30 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const app = express();
|
|
||||||
const port = 3000;
|
|
||||||
|
|
||||||
// set template engine to Pug
|
|
||||||
app.set('view engine', 'pug');
|
|
||||||
|
|
||||||
// Using express.urlencoded middleware
|
|
||||||
app.use(express.urlencoded({
|
|
||||||
extended: true
|
|
||||||
}));
|
|
||||||
|
|
||||||
// import route handlers
|
|
||||||
var homeRoutes = require('./routes/home');
|
|
||||||
var serverRoutes = require('./routes/server');
|
|
||||||
|
|
||||||
// define routes
|
|
||||||
app.get('/', homeRoutes.getIndex);
|
|
||||||
app.get('/server/create', serverRoutes.getCreate);
|
|
||||||
app.post('/server/create', serverRoutes.postCreate);
|
|
||||||
app.get('/server/:serverName/start', serverRoutes.getStart);
|
|
||||||
app.get('/server/:serverName/stop', serverRoutes.getStop);
|
|
||||||
|
|
||||||
// set Express to serve static files (ideally this is only used in development)
|
|
||||||
app.use(express.static('./static/'));
|
|
||||||
|
|
||||||
// start Express.js app
|
|
||||||
app.listen(port, () => {
|
|
||||||
console.log(`MCST has started and is listening on port ${port}.`);
|
|
||||||
});
|
|
9
mcst.go
Normal file
9
mcst.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.metaunix.net/BitGoblin/mcst/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cmd.Start()
|
||||||
|
}
|
1706
package-lock.json
generated
1706
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "mcst",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"description": "Minecraft Java edition server management tool",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"start": "node index.js",
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "gitea@git.metaunix.net:BitGoblin/mcst.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"minecraft",
|
|
||||||
"minecraft java edition",
|
|
||||||
"java"
|
|
||||||
],
|
|
||||||
"author": "Gregory Ballantine <gballantine@bitgoblin.tech>",
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"dependencies": {
|
|
||||||
"config": "^3.3.8",
|
|
||||||
"express": "^4.18.1",
|
|
||||||
"pug": "^3.0.2"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
const config = require('config');
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const minecraft = require('../app/MinecraftServer');
|
|
||||||
|
|
||||||
exports.getIndex = function(req, res) {
|
|
||||||
// search for minecraft server directories
|
|
||||||
let rootDir = config.get('server_directory');
|
|
||||||
let serverDirs = fs.readdirSync(rootDir);
|
|
||||||
let servers = [];
|
|
||||||
for (let i = 0; i < serverDirs.length; i++) {
|
|
||||||
servers.push(new minecraft.Server(path.join(rootDir, serverDirs[i])));
|
|
||||||
}
|
|
||||||
|
|
||||||
// render view
|
|
||||||
res.render('index', {
|
|
||||||
servers: servers,
|
|
||||||
});
|
|
||||||
};
|
|
@ -1,70 +0,0 @@
|
|||||||
const config = require('config');
|
|
||||||
const fs = require('fs');
|
|
||||||
const https = require('https');
|
|
||||||
const path = require('path');
|
|
||||||
const minecraft = require('../app/MinecraftServer');
|
|
||||||
|
|
||||||
exports.getCreate = function(req, res) {
|
|
||||||
// render view
|
|
||||||
res.render('create');
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.postCreate = function(req, res) {
|
|
||||||
mcDir = config.get('server_directory');
|
|
||||||
serverDir = path.join(mcDir, req.body.serverName);
|
|
||||||
|
|
||||||
// make server directory
|
|
||||||
fs.mkdirSync(serverDir);
|
|
||||||
|
|
||||||
// grab the server JAR file
|
|
||||||
serverJarUrl = 'https://piston-data.mojang.com/v1/objects/f69c284232d7c7580bd89a5a4931c3581eae1378/server.jar';
|
|
||||||
serverJarName = "server_" + req.body.serverVersion + ".jar";
|
|
||||||
serverJarPath = path.join(serverDir, serverJarName);
|
|
||||||
https.get(serverJarUrl, (res) => {
|
|
||||||
const filePath = fs.createWriteStream(serverJarPath);
|
|
||||||
res.pipe(filePath);
|
|
||||||
filePath.on('finish', () => {
|
|
||||||
filePath.close();
|
|
||||||
console.log('Download Completed');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// create the start.sh shell script
|
|
||||||
scriptFilePath = path.join(serverDir, 'start.sh');
|
|
||||||
scriptContent = "#!/bin/sh\n\ncd " + serverDir + "\njava -Xmx2048M -Xms2048M -jar server_" + req.body.serverVersion + ".jar nogui &\n\necho \"$!\" > ./pid.txt";
|
|
||||||
fs.writeFileSync(scriptFilePath, scriptContent);
|
|
||||||
fs.chmodSync(scriptFilePath, 0o755);
|
|
||||||
|
|
||||||
// save the current version to a text file - this will hopefully be temporary solution
|
|
||||||
versionFilePath = path.join(serverDir, 'current_version.txt');
|
|
||||||
versionContent = req.body.serverVersion;
|
|
||||||
fs.writeFileSync(versionFilePath, versionContent);
|
|
||||||
fs.chmodSync(versionFilePath, 0o644);
|
|
||||||
|
|
||||||
// redirect the user back to the home page
|
|
||||||
res.redirect('/');
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.getStart = function(req, res) {
|
|
||||||
let serverName = req.params.serverName;
|
|
||||||
let rootDir = config.get('server_directory');
|
|
||||||
let server = new minecraft.Server(path.join(rootDir, serverName));
|
|
||||||
|
|
||||||
// start the server
|
|
||||||
server.start();
|
|
||||||
|
|
||||||
// redirect the user back to the home page
|
|
||||||
res.redirect('/');
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.getStop = function(req, res) {
|
|
||||||
let serverName = req.params.serverName;
|
|
||||||
let rootDir = config.get('server_directory');
|
|
||||||
let server = new minecraft.Server(path.join(rootDir, serverName));
|
|
||||||
|
|
||||||
// stop the server
|
|
||||||
server.stop();
|
|
||||||
|
|
||||||
// redirect the user back to the home page
|
|
||||||
res.redirect('/');
|
|
||||||
};
|
|
@ -1,46 +0,0 @@
|
|||||||
body{
|
|
||||||
background-color: #e6e6e6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the max-width for centered content */
|
|
||||||
.container{
|
|
||||||
max-width: 1100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main-content{
|
|
||||||
margin-top: 25px;
|
|
||||||
padding: 12px 25px;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* global navigation bar styles */
|
|
||||||
.navbar{
|
|
||||||
padding: 10px 18px;
|
|
||||||
background-color: #212121;
|
|
||||||
color: white;
|
|
||||||
font-size: 2.5rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar ul{
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar li{
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
.navbar li:not(:first-child){
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar li>a{
|
|
||||||
color: #eee;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: color 220ms ease-in-out;
|
|
||||||
}
|
|
||||||
.navbar li>a:hover{
|
|
||||||
color: white;
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
$(document).ready(function () {
|
|
||||||
// This will be used when needed
|
|
||||||
});
|
|
23
util/env.go
Normal file
23
util/env.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"os/user"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ResolveTilde(path string) string {
|
||||||
|
usr, _ := user.Current()
|
||||||
|
dir := usr.HomeDir
|
||||||
|
|
||||||
|
if path == "~" {
|
||||||
|
// In case of "~", which won't be caught by the "else if"
|
||||||
|
path = dir
|
||||||
|
} else if strings.HasPrefix(path, "~/") {
|
||||||
|
// Use strings.HasPrefix so we don't match paths like
|
||||||
|
// "/something/~/something/"
|
||||||
|
path = filepath.Join(dir, path[2:])
|
||||||
|
}
|
||||||
|
|
||||||
|
return path
|
||||||
|
}
|
29
util/env_test.go
Normal file
29
util/env_test.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
// define our test suite struct
|
||||||
|
type EnvTestSuite struct {
|
||||||
|
suite.Suite
|
||||||
|
}
|
||||||
|
|
||||||
|
// the tilde should expand to user's home directory
|
||||||
|
func (s *EnvTestSuite) TestResolveTilde() {
|
||||||
|
resolvedPath := ResolveTilde("~")
|
||||||
|
assert.NotEqual(s.T(), resolvedPath, "~")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure the tilde + relative path gets expanded fully
|
||||||
|
func (s *EnvTestSuite) TestResolveTildePath() {
|
||||||
|
resolvedPath := ResolveTilde("~/test")
|
||||||
|
assert.NotEqual(s.T(), resolvedPath, "~/test")
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is needed to run the test suite
|
||||||
|
func TestEnvTestSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(EnvTestSuite))
|
||||||
|
}
|
@ -1,24 +0,0 @@
|
|||||||
extends layout.pug
|
|
||||||
|
|
||||||
block content
|
|
||||||
header.row
|
|
||||||
div.columns.twelve
|
|
||||||
h1 Create new server
|
|
||||||
|
|
||||||
section.row
|
|
||||||
div.columns.twelve
|
|
||||||
form(action='/server/create', method='POST')
|
|
||||||
div.row
|
|
||||||
div.columns.six
|
|
||||||
label(for='serverName') Server name:
|
|
||||||
input#serverName.u-full-width(name='serverName', type='text', placeholder='MyServer')
|
|
||||||
div.columns.six
|
|
||||||
label(for='serverVersion') Minecraft version:
|
|
||||||
input#serverVersion.u-full-width(name='serverVersion', type='text', placeholder='1.19.2')
|
|
||||||
|
|
||||||
input(type='submit', value='Submit')
|
|
||||||
|
|
||||||
div.row
|
|
||||||
div.columns.twelve
|
|
||||||
p
|
|
||||||
a(href='/') Back
|
|
@ -1,30 +0,0 @@
|
|||||||
extends layout.pug
|
|
||||||
|
|
||||||
block content
|
|
||||||
header.row
|
|
||||||
div.columns.twelve
|
|
||||||
h1 Welcome to MCST!
|
|
||||||
p Using MCST you can easily manage your Minecraft: Java Edition servers.
|
|
||||||
|
|
||||||
section.row
|
|
||||||
div.columns.twelve
|
|
||||||
h3 List of servers:
|
|
||||||
if servers.length < 1
|
|
||||||
p There are currently no servers registered.
|
|
||||||
else
|
|
||||||
table.u-full-width
|
|
||||||
thead
|
|
||||||
tr
|
|
||||||
th Server name
|
|
||||||
th Minecraft version
|
|
||||||
th State
|
|
||||||
th Actions
|
|
||||||
tbody
|
|
||||||
each m in servers
|
|
||||||
tr.serverItem
|
|
||||||
td.serverName= m.name
|
|
||||||
td.serverVersion= m.version
|
|
||||||
td.serverState= m.getStatus()
|
|
||||||
td
|
|
||||||
a(href='/server/' + m.name + '/start') Start
|
|
||||||
a(href='/server/' + m.name + '/stop') Stop
|
|
@ -1,21 +0,0 @@
|
|||||||
doctype html
|
|
||||||
html(lang="en")
|
|
||||||
head
|
|
||||||
title= pageTitle
|
|
||||||
link(rel='stylesheet', href='https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css')
|
|
||||||
link(rel='stylesheet', href='/css/wyrm.css')
|
|
||||||
script(src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js')
|
|
||||||
script(src='/js/drake.js')
|
|
||||||
body
|
|
||||||
// global navigation
|
|
||||||
nav.navbar
|
|
||||||
div.navbar-left
|
|
||||||
ul
|
|
||||||
li.menu-text MCST
|
|
||||||
li: a(href='/') Home
|
|
||||||
li: a(href='/server/create') Create
|
|
||||||
li: a(href='/status') Status
|
|
||||||
|
|
||||||
// main content
|
|
||||||
div#main-content.container
|
|
||||||
block content
|
|
Reference in New Issue
Block a user