Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
f908be29b9 | |||
ccce234ae3 | |||
92153508b3 |
29
.gitignore
vendored
29
.gitignore
vendored
@ -1,5 +1,26 @@
|
|||||||
# Composer dependencies
|
# ---> Go
|
||||||
vendor/
|
# 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
|
||||||
|
|
||||||
# PHP CodeSniffer cache
|
|
||||||
.phpcs-cache
|
|
||||||
|
@ -1,30 +1,22 @@
|
|||||||
pipeline:
|
pipeline:
|
||||||
setup:
|
build_test:
|
||||||
image: composer:2.4
|
image: golang:1.16
|
||||||
commands:
|
commands:
|
||||||
- composer install
|
- go build
|
||||||
- mkdir test
|
|
||||||
- touch test/results.txt
|
|
||||||
|
|
||||||
phpcs:
|
test:
|
||||||
group: test
|
image: golang:1.16
|
||||||
image: composer:2.4
|
|
||||||
commands:
|
commands:
|
||||||
- composer run-script phpcs >> test/results.txt
|
- go test -v ./...
|
||||||
phpmd:
|
|
||||||
group: test
|
|
||||||
image: composer:2.4
|
|
||||||
commands:
|
|
||||||
- composer run-script phpmd >> test/results.txt
|
|
||||||
|
|
||||||
notify:
|
build_release:
|
||||||
image: drillster/drone-email
|
image: golang:1.16
|
||||||
host: smtp.int.metaunix.net
|
commands:
|
||||||
skip_verify: true
|
- go mod vendor
|
||||||
from: drone@ci-v1.int.metaunix.net
|
- 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}"
|
||||||
attachment: test/results.txt
|
- 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:
|
when:
|
||||||
status: [ failure ]
|
event: tag
|
||||||
|
|
||||||
gitea_release:
|
gitea_release:
|
||||||
image: plugins/gitea-release
|
image: plugins/gitea-release
|
||||||
@ -33,5 +25,7 @@ pipeline:
|
|||||||
from_secret: gitea_api_key
|
from_secret: gitea_api_key
|
||||||
base_url: https://git.metaunix.net
|
base_url: https://git.metaunix.net
|
||||||
title: "${CI_COMMIT_TAG}"
|
title: "${CI_COMMIT_TAG}"
|
||||||
|
files:
|
||||||
|
- dist/mcst-*
|
||||||
when:
|
when:
|
||||||
event: tag
|
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,4 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# start a local instance of the app using PHP's built-in webserver
|
|
||||||
php -S localhost:8080 -t public/ public/index.php
|
|
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,33 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "bitgoblin/mcst",
|
|
||||||
"description": "Minecraft Java Edition server management tool",
|
|
||||||
"type": "project",
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"BitGoblin\\MCST\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Gregory Ballantine",
|
|
||||||
"email": "gballantine@bitgoblin.tech"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"slim/slim": "^4.10",
|
|
||||||
"slim/psr7": "^1.5",
|
|
||||||
"slim/twig-view": "^3.3",
|
|
||||||
"hassankhan/config": "^3.0",
|
|
||||||
"php-di/php-di": "^6.4",
|
|
||||||
"imangazaliev/didom": "^1.13"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"squizlabs/php_codesniffer": "^3.5",
|
|
||||||
"phpmd/phpmd": "^2.5"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"phpcs": "phpcs --standard=./phpcs.xml",
|
|
||||||
"phpmd": "phpmd src/ text phpmd.xml"
|
|
||||||
}
|
|
||||||
}
|
|
2213
composer.lock
generated
2213
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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=
|
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()
|
||||||
|
}
|
35
phpcs.xml
35
phpcs.xml
@ -1,35 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
|
|
||||||
<ruleset name="PHP_CodeSniffer">
|
|
||||||
|
|
||||||
<description>PHPCS configuration file.</description>
|
|
||||||
|
|
||||||
<arg name="basepath" value="." />
|
|
||||||
<arg name="extensions" value="php" />
|
|
||||||
<arg name="colors" />
|
|
||||||
<arg name="cache" value=".phpcs-cache" />
|
|
||||||
<arg value="p" />
|
|
||||||
<arg value="s" />
|
|
||||||
|
|
||||||
<!-- Check PHP files in the src/ directory -->
|
|
||||||
<file>src/</file>
|
|
||||||
|
|
||||||
<!-- Our base rule: set to PSR12-->
|
|
||||||
<rule ref="PSR12">
|
|
||||||
<exclude name="PSR12.Classes.OpeningBraceSpace.Found" />
|
|
||||||
<exclude name="PSR2.Classes.ClassDeclaration.OpenBraceNewLine" />
|
|
||||||
<exclude name="PSR2.Classes.ClassDeclaration.CloseBraceAfterBody" />
|
|
||||||
<exclude name="Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine" />
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<!-- Some custom rules -->
|
|
||||||
<rule ref="Generic.Functions.OpeningFunctionBraceKernighanRitchie" />
|
|
||||||
<rule ref="Generic.Classes.OpeningBraceSameLine" />
|
|
||||||
<!-- Set indent size to 2 -->
|
|
||||||
<rule ref="Generic.WhiteSpace.ScopeIndent">
|
|
||||||
<properties>
|
|
||||||
<property name="indent" value="2" />
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
</ruleset>
|
|
19
phpmd.xml
19
phpmd.xml
@ -1,19 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<ruleset name="PHP CMS rule set"
|
|
||||||
xmlns="http://pmd.sf.net/ruleset/1.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0
|
|
||||||
http://pmd.sf.net/ruleset_xml_schema.xsd"
|
|
||||||
xsi:noNamespaceSchemaLocation="
|
|
||||||
http://pmd.sf.net/ruleset_xml_schema.xsd">
|
|
||||||
<description>
|
|
||||||
Custom rule set for Pigeon Discord notifier project.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<!-- Import some rule sets -->
|
|
||||||
<rule ref="rulesets/cleancode.xml" />
|
|
||||||
<rule ref="rulesets/codesize.xml" />
|
|
||||||
<rule ref="rulesets/design.xml" />
|
|
||||||
<rule ref="rulesets/naming.xml" />
|
|
||||||
<rule ref="rulesets/unusedcode.xml" />
|
|
||||||
</ruleset>
|
|
@ -1 +0,0 @@
|
|||||||
628624
|
|
@ -1,5 +0,0 @@
|
|||||||
# rewrite rules
|
|
||||||
RewriteEngine On
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
|
||||||
RewriteCond %{REQUEST_FILENAME} !-d
|
|
||||||
RewriteRule ^ index.php [QSA,L]
|
|
@ -1,58 +0,0 @@
|
|||||||
body{
|
|
||||||
background-color: #e6e6e6;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=submit]:disabled,
|
|
||||||
button:disabled{
|
|
||||||
background-color: darkgrey;
|
|
||||||
}
|
|
||||||
input[type=submit]:disabled:hover,
|
|
||||||
button:disabled:hover{
|
|
||||||
background-color: darkgrey;
|
|
||||||
border: 1px solid #bbb;
|
|
||||||
color: #555;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// if we're looking for static files in dev, return false so they can be served.
|
|
||||||
if (PHP_SAPI == 'cli-server') {
|
|
||||||
$url = parse_url($_SERVER['REQUEST_URI']);
|
|
||||||
$file = __DIR__ . $url['path'];
|
|
||||||
|
|
||||||
// check the file types, only serve standard files
|
|
||||||
if (preg_match('/\.(?:png|js|jpg|jpeg|gif|css)$/', $file)) {
|
|
||||||
// does the file exist? If so, return it
|
|
||||||
if (is_file($file))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// file does not exist. return a 404
|
|
||||||
header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
|
|
||||||
printf('"%s" does not exist', $_SERVER['REQUEST_URI']);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../src/app.php';
|
|
||||||
|
|
||||||
$app->run();
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
$(document).ready(function () {
|
|
||||||
// periodically check for server status updates
|
|
||||||
$('.serverItem').each(function() {
|
|
||||||
setInterval(updateServer, 5000, $(this));
|
|
||||||
});
|
|
||||||
|
|
||||||
// set the serverName input field to check if the server exists
|
|
||||||
$('input#serverName').on('change', checkServerExists);
|
|
||||||
});
|
|
||||||
|
|
||||||
function updateServer(elem) {
|
|
||||||
var serverName = elem.data('server-name');
|
|
||||||
$.get('/server/' + serverName + '/status', function(data, state) {
|
|
||||||
elem.children('.serverState').eq(0).text(data.state);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkServerExists() {
|
|
||||||
$.get('/server/' + $(this).val() + '/status', function(data, state) {
|
|
||||||
if (data.exists) {
|
|
||||||
$('input#createSubmit').prop('disabled', true);
|
|
||||||
alert('That server name is already used; please use another name!');
|
|
||||||
} else {
|
|
||||||
if ($('input#createSubmit').prop('disabled')) {
|
|
||||||
$('input#createSubmit').prop('disabled', false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace BitGoblin\MCST\Controllers;
|
|
||||||
|
|
||||||
use Psr\Container\ContainerInterface;
|
|
||||||
|
|
||||||
class Controller {
|
|
||||||
|
|
||||||
protected $container;
|
|
||||||
|
|
||||||
public function __construct(ContainerInterface $container) {
|
|
||||||
$this->container = $container;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get(string $name) {
|
|
||||||
return $this->container->get($name);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace BitGoblin\MCST\Controllers;
|
|
||||||
|
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
|
||||||
use Slim\Views\Twig;
|
|
||||||
use BitGoblin\MCST\Minecraft\Server;
|
|
||||||
|
|
||||||
class HomeController extends Controller {
|
|
||||||
|
|
||||||
public function getIndex(Request $request, Response $response): Response {
|
|
||||||
$config = $this->get('config');
|
|
||||||
|
|
||||||
// find servers
|
|
||||||
$minecraftDir = $config->get('server_directory');
|
|
||||||
$serverDirs = glob($minecraftDir . "/*", GLOB_ONLYDIR);
|
|
||||||
$minecraftServers = array();
|
|
||||||
foreach ($serverDirs as $m) {
|
|
||||||
array_push($minecraftServers, new Server($m));
|
|
||||||
}
|
|
||||||
|
|
||||||
$view = Twig::fromRequest($request);
|
|
||||||
return $view->render($response, 'index.twig', [
|
|
||||||
'servers' => $minecraftServers,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,151 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace BitGoblin\MCST\Controllers;
|
|
||||||
|
|
||||||
use DiDom\Document;
|
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
|
||||||
use Slim\Views\Twig;
|
|
||||||
use BitGoblin\MCST\Minecraft\Server;
|
|
||||||
|
|
||||||
class ServerController extends Controller {
|
|
||||||
|
|
||||||
// GET create server route
|
|
||||||
public function getCreate(Request $request, Response $response): Response {
|
|
||||||
$view = Twig::fromRequest($request);
|
|
||||||
return $view->render($response, 'create.twig');
|
|
||||||
}
|
|
||||||
|
|
||||||
// POST create server route
|
|
||||||
public function postCreate(Request $request, Response $response): Response {
|
|
||||||
// set up the POST parameters and grab our config
|
|
||||||
$params = (array)$request->getParsedBody();
|
|
||||||
$config = $this->get('config');
|
|
||||||
|
|
||||||
// create our server directory
|
|
||||||
$serverDir = join('/', array($config->get('server_directory'), $params['serverName']));
|
|
||||||
mkdir($serverDir);
|
|
||||||
|
|
||||||
// find the server JAR URL for the version
|
|
||||||
$versionPageLink = 'https://minecraft.fandom.com/wiki/Java_Edition_' . $params['serverVersion'];
|
|
||||||
$dom = new Document($versionPageLink, true);
|
|
||||||
$infobox = $dom->find('.notaninfobox')[0];
|
|
||||||
$serverLinkElem = $infobox->find("a:contains('Server')");
|
|
||||||
$serverJarUrl = $serverLinkElem[0]->attr('href');
|
|
||||||
|
|
||||||
// grab the server JAR file
|
|
||||||
$serverJarName = "server_" . $params['serverVersion'] . ".jar";
|
|
||||||
$serverJarPath = join('/', array($serverDir, $serverJarName));
|
|
||||||
file_put_contents($serverJarPath, file_get_contents($serverJarUrl));
|
|
||||||
|
|
||||||
// create the start.sh shell script
|
|
||||||
$scriptFilePath = join('/', array($serverDir, 'start.sh'));
|
|
||||||
$scriptFile = fopen($scriptFilePath, 'w');
|
|
||||||
$scriptContent = "#!/bin/sh\n\ncd " . $serverDir . "\njava -Xmx2048M -Xms2048M -jar server_" . $params['serverVersion'] . ".jar nogui";
|
|
||||||
fwrite($scriptFile, $scriptContent);
|
|
||||||
fclose($scriptFile);
|
|
||||||
chmod($scriptFilePath, 0755);
|
|
||||||
|
|
||||||
// save the current version to a text file - this will hopefully be temporary solution
|
|
||||||
$versionFilePath = join('/', array($serverDir, 'current_version.txt'));
|
|
||||||
$versionFile = fopen($versionFilePath, 'w');
|
|
||||||
$versionContent = $params['serverVersion'];
|
|
||||||
fwrite($versionFile, $versionContent);
|
|
||||||
fclose($versionFile);
|
|
||||||
chmod($versionFilePath, 0644);
|
|
||||||
|
|
||||||
// redirect the user back to the home page
|
|
||||||
return $response
|
|
||||||
->withHeader('Location', '/')
|
|
||||||
->withStatus(302);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET server status route
|
|
||||||
public function getStatus(Request $request, Response $response, $args): Response {
|
|
||||||
$config = $this->get('config');
|
|
||||||
$serverDir = join('/', array($config->get('server_directory'), $args['serverName']));
|
|
||||||
|
|
||||||
// check if the server exists - if not, return a false result
|
|
||||||
if (!is_dir($serverDir)) {
|
|
||||||
$response->getBody()->write(json_encode(array('exists' => false)));
|
|
||||||
return $response
|
|
||||||
->withHeader('Content-Type', 'application/json');
|
|
||||||
}
|
|
||||||
|
|
||||||
// create server object and pass info back to client as JSON data
|
|
||||||
$server = new Server($serverDir);
|
|
||||||
$serverData = [
|
|
||||||
'exists' => true,
|
|
||||||
'name' => $server->getName(),
|
|
||||||
'version' => $server->getVersion(),
|
|
||||||
'state' => $server->getState() ? 'Running' : 'Stopped',
|
|
||||||
];
|
|
||||||
|
|
||||||
$response->getBody()->write(json_encode($serverData));
|
|
||||||
return $response
|
|
||||||
->withHeader('Content-Type', 'application/json');
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET server start route
|
|
||||||
public function getStart(Request $request, Response $response, $args): Response {
|
|
||||||
$config = $this->get('config');
|
|
||||||
$serverDir = join('/', array($config->get('server_directory'), $args['serverName']));
|
|
||||||
|
|
||||||
// create server object and start it
|
|
||||||
$server = new Server($serverDir);
|
|
||||||
$server->start();
|
|
||||||
|
|
||||||
// redirect the user back to the home page
|
|
||||||
return $response
|
|
||||||
->withHeader('Location', '/')
|
|
||||||
->withStatus(302);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET server stop route
|
|
||||||
public function getStop(Request $request, Response $response, $args): Response {
|
|
||||||
$config = $this->get('config');
|
|
||||||
$serverDir = join('/', array($config->get('server_directory'), $args['serverName']));
|
|
||||||
|
|
||||||
// create server object and start it
|
|
||||||
$server = new Server($serverDir);
|
|
||||||
$server->stop();
|
|
||||||
|
|
||||||
// redirect the user back to the home page
|
|
||||||
return $response
|
|
||||||
->withHeader('Location', '/')
|
|
||||||
->withStatus(302);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET edit server properties route
|
|
||||||
public function getEdit(Request $request, Response $response, $args): Response {
|
|
||||||
$config = $this->get('config');
|
|
||||||
$serverDir = join('/', array($config->get('server_directory'), $args['serverName']));
|
|
||||||
|
|
||||||
$server = new Server($serverDir);
|
|
||||||
$data = array(
|
|
||||||
'serverName' => $args['serverName'],
|
|
||||||
'serverPort' => $server->getProperty('server-port'),
|
|
||||||
);
|
|
||||||
|
|
||||||
$view = Twig::fromRequest($request);
|
|
||||||
return $view->render($response, 'edit.twig', $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// POST edit server properties route
|
|
||||||
public function postEdit(Request $request, Response $response, $args): Response {
|
|
||||||
// set up the POST parameters and grab our config
|
|
||||||
$params = (array)$request->getParsedBody();
|
|
||||||
$config = $this->get('config');
|
|
||||||
$serverDir = join('/', array($config->get('server_directory'), $args['serverName']));
|
|
||||||
|
|
||||||
// create server object and save new value
|
|
||||||
$server = new Server($serverDir);
|
|
||||||
$server->updateProperty('server-port', $params['serverPort']);
|
|
||||||
|
|
||||||
// redirect the user back to the home page
|
|
||||||
return $response
|
|
||||||
->withHeader('Location', '/')
|
|
||||||
->withStatus(302);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,111 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace BitGoblin\MCST\Minecraft;
|
|
||||||
|
|
||||||
class Server {
|
|
||||||
|
|
||||||
// server root directory
|
|
||||||
private string $rootDir;
|
|
||||||
// server name
|
|
||||||
private string $serverName;
|
|
||||||
// server Minecraft version
|
|
||||||
private string $serverVersion;
|
|
||||||
// PID file path
|
|
||||||
private string $pidFilePath;
|
|
||||||
// server run status
|
|
||||||
private bool $state = false;
|
|
||||||
// server config properties
|
|
||||||
private ServerConfig $properties;
|
|
||||||
|
|
||||||
// class constructor
|
|
||||||
public function __construct($dir) {
|
|
||||||
$dirBits = explode('/', $dir);
|
|
||||||
$this->rootDir = $dir;
|
|
||||||
$this->serverName = $dirBits[count($dirBits) - 1];
|
|
||||||
$this->pidFilePath = $this->rootDir . '/pid.txt';
|
|
||||||
$this->properties = new ServerConfig($this->rootDir . '/server.properties');
|
|
||||||
|
|
||||||
// get server version
|
|
||||||
$versionFile = join('/', array($this->rootDir, 'current_version.txt'));
|
|
||||||
if (file_exists($versionFile)) {
|
|
||||||
$this->serverVersion = file($versionFile)[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// search for server PID file
|
|
||||||
if (file_exists($this->pidFilePath)) {
|
|
||||||
// get and search for PID
|
|
||||||
$pid = trim($this->getPid());
|
|
||||||
if (file_exists('/proc/' . $pid)) {
|
|
||||||
// set server state to true since it is running
|
|
||||||
$this->state = true;
|
|
||||||
} else {
|
|
||||||
// delete the PID file since it's no longer needed
|
|
||||||
unlink($this->pidFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// start the server
|
|
||||||
public function start(): void {
|
|
||||||
$command = $this->rootDir . '/start.sh > /dev/null 2>&1 & echo $!';
|
|
||||||
exec($command, $output);
|
|
||||||
// use lsof to find the PID of the server
|
|
||||||
$pidResult = exec('lsof ' . $this->rootDir . '/server*.jar | grep .jar');
|
|
||||||
$pid = preg_split('/\s+/', $pidResult, -1, PREG_SPLIT_NO_EMPTY)[1];
|
|
||||||
|
|
||||||
$pidFile = fopen($this->pidFilePath, 'w');
|
|
||||||
fwrite($pidFile, $pid);
|
|
||||||
fclose($pidFile);
|
|
||||||
|
|
||||||
// set server state to true
|
|
||||||
$this->state = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop the server
|
|
||||||
public function stop(): void {
|
|
||||||
$pid = $this->getPid();
|
|
||||||
if ($pid != -1) {
|
|
||||||
// kill the process gracefully
|
|
||||||
exec('kill -15 ' . $pid);
|
|
||||||
// set server state to false
|
|
||||||
$this->state = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the server's PID
|
|
||||||
private function getPid(): int {
|
|
||||||
// search for server PID file
|
|
||||||
if (file_exists($this->pidFilePath)) {
|
|
||||||
// get and return server PID
|
|
||||||
return trim(file($this->pidFilePath)[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return a 'false' result
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get property from server properties file
|
|
||||||
public function getProperty(string $param) {
|
|
||||||
return $this->properties->get($param);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update property in server properties file
|
|
||||||
public function updateProperty(string $paramName, $paramValue) {
|
|
||||||
$this->properties->update($paramName, $paramValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// getters & setters
|
|
||||||
public function getDirectory(): string {
|
|
||||||
return $this->rootDir;
|
|
||||||
}
|
|
||||||
public function getName(): string {
|
|
||||||
return $this->serverName;
|
|
||||||
}
|
|
||||||
public function getVersion(): string {
|
|
||||||
return $this->serverVersion;
|
|
||||||
}
|
|
||||||
public function getState(): bool {
|
|
||||||
return $this->state;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace BitGoblin\MCST\Minecraft;
|
|
||||||
|
|
||||||
class ServerConfig {
|
|
||||||
|
|
||||||
// path to the server.properties file
|
|
||||||
protected string $propertiesFile;
|
|
||||||
// loaded properties
|
|
||||||
protected array $config;
|
|
||||||
|
|
||||||
public function __construct($propertiesFile) {
|
|
||||||
$this->propertiesFile = $propertiesFile; // save the properties file
|
|
||||||
$this->config = array(); // initialize array
|
|
||||||
|
|
||||||
// parse config file
|
|
||||||
$fileHandle = fopen($propertiesFile, 'r+');
|
|
||||||
while (!feof($fileHandle)) {
|
|
||||||
$line = fgets($fileHandle);
|
|
||||||
$eqpos = strpos($line, '=');
|
|
||||||
$parameterName = substr($line, 0, $eqpos);
|
|
||||||
$parameterValue = trim(substr($line, ($eqpos + 1)));
|
|
||||||
|
|
||||||
// assign parameter values to the config array
|
|
||||||
$this->config[$parameterName] = $parameterValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get(string $param) {
|
|
||||||
return $this->config[$param];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update(string $paramName, $paramValue) {
|
|
||||||
// update the local variable value
|
|
||||||
$this->config[$paramName] = $paramValue;
|
|
||||||
|
|
||||||
// update and save the server.properties file
|
|
||||||
$newFileContent = '';
|
|
||||||
$fileHandle = fopen($this->propertiesFile, 'r+');
|
|
||||||
while (!feof($fileHandle)) {
|
|
||||||
$line = fgets($fileHandle);
|
|
||||||
|
|
||||||
if (!str_starts_with($line, '#')) {
|
|
||||||
$eqpos = strpos($line, '=');
|
|
||||||
$parameterName = substr($line, 0, $eqpos);
|
|
||||||
$parameterValue = substr($line, ($eqpos + 1));
|
|
||||||
|
|
||||||
// use the new value if it's being updated
|
|
||||||
if ($parameterName == $paramName) {
|
|
||||||
$parameterValue = $paramValue . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$newFileContent .= $parameterName . '=' . $parameterValue;
|
|
||||||
} else {
|
|
||||||
$newFileContent .= $line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the new properties file
|
|
||||||
file_put_contents($this->propertiesFile, $newFileContent);
|
|
||||||
fclose($fileHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
35
src/app.php
35
src/app.php
@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use DI\Container;
|
|
||||||
use Noodlehaus\Config;
|
|
||||||
use Noodlehaus\Parser\Json;
|
|
||||||
use Slim\Factory\AppFactory;
|
|
||||||
use Slim\Views\Twig;
|
|
||||||
use Slim\Views\TwigMiddleware;
|
|
||||||
|
|
||||||
require __DIR__ . '/../vendor/autoload.php';
|
|
||||||
|
|
||||||
// Load app configuration
|
|
||||||
$config = Config::load(__DIR__ . '/../conf/defaults.json');
|
|
||||||
|
|
||||||
// Create new container object and add our config object to it
|
|
||||||
$container = new Container();
|
|
||||||
$container->set('config', function () use ($config) {
|
|
||||||
return $config;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set container to create App with on AppFactory
|
|
||||||
AppFactory::setContainer($container);
|
|
||||||
$app = AppFactory::create();
|
|
||||||
|
|
||||||
// Add Error Handling Middleware
|
|
||||||
$app->addErrorMiddleware(true, false, false);
|
|
||||||
|
|
||||||
// Create Twig
|
|
||||||
$twig = Twig::create(__DIR__ . '/../views', ['cache' => false]);
|
|
||||||
|
|
||||||
// Add Twig-View Middleware
|
|
||||||
$app->add(TwigMiddleware::create($app, $twig));
|
|
||||||
|
|
||||||
// load in route handlers
|
|
||||||
require_once __DIR__ . '/routes.php';
|
|
@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
|
||||||
use Slim\Views\Twig;
|
|
||||||
use BitGoblin\MCST\Minecraft\Server;
|
|
||||||
|
|
||||||
// index GET route - this page should welcome the user and direct them to the available actions
|
|
||||||
$app->get('/', '\\BitGoblin\\MCST\\Controllers\\HomeController:getIndex')->setName('index');
|
|
||||||
|
|
||||||
// create GET route - this page allows a user to create a new server instance
|
|
||||||
$app->get('/create', '\\BitGoblin\\MCST\\Controllers\\ServerController:getCreate')->setName('create');
|
|
||||||
// create POST route - processes the new server creation
|
|
||||||
$app->post('/create', '\\BitGoblin\\MCST\\Controllers\\ServerController:postCreate');
|
|
||||||
|
|
||||||
// server status route
|
|
||||||
$app->get('/server/{serverName}/status', '\\BitGoblin\\MCST\\Controllers\\ServerController:getStatus')->setName('server.status');
|
|
||||||
|
|
||||||
// server start route
|
|
||||||
$app->get('/server/{serverName}/start', '\\BitGoblin\\MCST\\Controllers\\ServerController:getStart')->setName('server.start');
|
|
||||||
// server stop route
|
|
||||||
$app->get('/server/{serverName}/stop', '\\BitGoblin\\MCST\\Controllers\\ServerController:getStop')->setName('server.stop');
|
|
||||||
|
|
||||||
// edit GET route - this page allows a user to edit a server's properties
|
|
||||||
$app->get('/server/{serverName}/edit', '\\BitGoblin\\MCST\\Controllers\\ServerController:getEdit')->setName('edit');
|
|
||||||
// edit POST route - processes the edits a server's properties file
|
|
||||||
$app->post('/server/{serverName}/edit', '\\BitGoblin\\MCST\\Controllers\\ServerController:postEdit');
|
|
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,40 +0,0 @@
|
|||||||
{% extends 'layout.twig' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<!-- page header -->
|
|
||||||
<header class="row">
|
|
||||||
<div class="columns twelve">
|
|
||||||
<h1>Create new server</h1>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- create server form -->
|
|
||||||
<section class="row">
|
|
||||||
<div class="columns twelve">
|
|
||||||
<form action="/create" method="POST">
|
|
||||||
<div class="row">
|
|
||||||
<div class="columns six">
|
|
||||||
<label for="serverName">Server name:</label>
|
|
||||||
<input id="serverName" name="serverName" class="u-full-width" type="text" placeholder="MyServer" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="columns six">
|
|
||||||
<label for="serverVersion">Minecraft version:</label>
|
|
||||||
<input id="serverVersion" name="serverVersion" class="u-full-width" type="text" placeholder="1.19.2" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input id="createSubmit" type="submit" value="Submit">
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- lower navigation -->
|
|
||||||
<div class="row">
|
|
||||||
<div class="columns twelve">
|
|
||||||
<p><a href="/">Back</a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -1,35 +0,0 @@
|
|||||||
{% extends 'layout.twig' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<!-- page header -->
|
|
||||||
<header class="row">
|
|
||||||
<div class="columns twelve">
|
|
||||||
<h1>Edit server: {{ serverName }}</h1>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- create server form -->
|
|
||||||
<section class="row">
|
|
||||||
<div class="columns twelve">
|
|
||||||
<form action="/server/{{ serverName }}/edit" method="POST">
|
|
||||||
<div class="row">
|
|
||||||
<div class="columns twelve">
|
|
||||||
<label for="serverPort">Server port:</label>
|
|
||||||
<input id="serverPort" name="serverPort" class="u-full-width" type="number" placeholder="25565" required value={{ serverPort }}>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<input id="editSubmit" type="submit" value="Submit">
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- lower navigation -->
|
|
||||||
<div class="row">
|
|
||||||
<div class="columns twelve">
|
|
||||||
<p><a href="/">Back</a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -1,50 +0,0 @@
|
|||||||
{% extends 'layout.twig' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<!-- page header -->
|
|
||||||
<header class="row">
|
|
||||||
<div class="columns twelve">
|
|
||||||
<h1>Welcome to MCST!</h1>
|
|
||||||
<p>Using MCST you can easily manage your Minecraft: Java Edition servers.</p>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- list of servers -->
|
|
||||||
<section class="row">
|
|
||||||
<div class="columns twelve">
|
|
||||||
<h3>List of servers:</h3>
|
|
||||||
{% if servers|length < 1 %}
|
|
||||||
<p>There are currently no servers registered.</p>
|
|
||||||
{% else %}
|
|
||||||
<table class="u-full-width">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Server name</th>
|
|
||||||
<th>Minecraft version</th>
|
|
||||||
<th>Port</th>
|
|
||||||
<th>State</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for m in servers %}
|
|
||||||
<tr class="serverItem" data-server-name="{{ m.getName() }}">
|
|
||||||
<td class="serverName">{{ m.getName() }}</td>
|
|
||||||
<td class="serverVersion">{{ m.getVersion() }}</td>
|
|
||||||
<td class="serverPort">{{ m.getProperty('server-port') }}</td>
|
|
||||||
<td class="serverState">{{ m.getState() ? 'Running' : 'Stopped' }}</td>
|
|
||||||
<td>
|
|
||||||
<a href="/server/{{ m.getName() }}/start"><i class="fa-solid fa-play"></i></a>
|
|
||||||
<a href="/server/{{ m.getName() }}/stop"><i class="fa-solid fa-stop"></i></a>
|
|
||||||
<a href="/server/{{ m.getName() }}/edit"><i class="fa-solid fa-pen-to-square"></i></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -1,32 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Minecraft Server Tool</title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
|
|
||||||
<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>
|
|
||||||
<script src="/js/drake.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<!-- global navigation -->
|
|
||||||
<nav class="navbar">
|
|
||||||
<div class="navbar-left">
|
|
||||||
<ul>
|
|
||||||
<li class="menu-text">MCST</li>
|
|
||||||
<li><a href="/">Home</a></li>
|
|
||||||
<li><a href="/create">Create</a></li>
|
|
||||||
<li><a href="/status">Status</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!-- main content -->
|
|
||||||
<div id="main-content" class="container">
|
|
||||||
{% block content %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Loading…
Reference in New Issue
Block a user