mirror of
https://github.com/hamburghammer/rcon-cli.git
synced 2024-05-18 02:34:36 +02:00
Augusto Dwenger J.
3e532d98c5
Minecrafts server implementation doesn't behave like valves and the SimpleClient followes strictly the documentation from valve. Switching the implementation I also refactored the code so that future implementation changes won't change mutch due to the usage of an interface.
162 lines
3.3 KiB
Go
162 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/hamburghammer/grcon"
|
|
"github.com/hamburghammer/grcon/client"
|
|
"github.com/hamburghammer/grcon/util"
|
|
flags "github.com/spf13/pflag"
|
|
)
|
|
|
|
const (
|
|
defaultHost = "localhost"
|
|
defaultPort = "25575"
|
|
defaultPassword = ""
|
|
|
|
envVarPrefix = "RCON_CLI_"
|
|
)
|
|
|
|
// vars holding the parsed configuration
|
|
var (
|
|
host string
|
|
port string
|
|
password string
|
|
help bool
|
|
)
|
|
|
|
func main() {
|
|
commands, _ := parseArgs(os.Args[1:])
|
|
loadEnvIfNotSet()
|
|
if help {
|
|
printHelp()
|
|
os.Exit(0)
|
|
return
|
|
}
|
|
|
|
err := run(strings.Join(commands, " "))
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err.Error())
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func parseArgs(args []string) ([]string, error) {
|
|
flags.StringVar(&host, "host", defaultHost, "RCON server's hostname.")
|
|
flags.StringVar(&port, "port", defaultPort, "RCON server's port.")
|
|
flags.StringVar(&password, "password", defaultPassword, "RCON server's password.")
|
|
flags.BoolVarP(&help, "help", "h", false, "Prints this help message and exits.")
|
|
|
|
err := flags.CommandLine.Parse(args)
|
|
if err != nil {
|
|
return []string{}, err
|
|
}
|
|
|
|
command := flags.Args()
|
|
|
|
return command, nil
|
|
}
|
|
|
|
func loadEnvIfNotSet() {
|
|
envHost := os.Getenv(fmt.Sprintf("%sHOST", envVarPrefix))
|
|
if envHost != "" && host == defaultHost {
|
|
host = envHost
|
|
}
|
|
|
|
envPort := os.Getenv(fmt.Sprintf("%sPORT", envVarPrefix))
|
|
if envPort != "" && port == defaultPort {
|
|
port = envPort
|
|
}
|
|
|
|
envPassword := os.Getenv(fmt.Sprintf("%sPASSWORD", envVarPrefix))
|
|
if envPassword != "" && password == defaultPassword {
|
|
password = envPassword
|
|
}
|
|
}
|
|
|
|
func run(cmd string) error {
|
|
hostPort := net.JoinHostPort(host, port)
|
|
conn, err := net.Dial("tcp", hostPort)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
remoteConsole := grcon.NewRemoteConsole(conn)
|
|
rconClient := client.NewMinecraftClient(remoteConsole, util.GenerateRequestId)
|
|
err = rconClient.Auth(password)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to authenticate: %w", err)
|
|
}
|
|
|
|
if len(cmd) == 0 {
|
|
err = executeInteractive(rconClient)
|
|
} else {
|
|
resp, err := execute(cmd, rconClient)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Println(resp)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func printHelp() {
|
|
fmt.Println(`rcon-cli is a CLI to interact with a RCON server.
|
|
It can be run in an interactive mode or to execute a single command.
|
|
|
|
USAGE:
|
|
rcon-cli [FLAGS] [RCON command ...]
|
|
|
|
FLAGS:`)
|
|
flags.PrintDefaults()
|
|
fmt.Printf(`
|
|
ENVIRONMENT VARIABLE:
|
|
All flags can be set through the flag name in capslock with the %s prefix (see examples).
|
|
Flags have allways priority over env vars!
|
|
|
|
EXAMPLES:
|
|
rcon-cli --host 127.0.0.1 --port 25575
|
|
rcon-cli --password admin123 stop
|
|
%sPORT=25575 rcon-cli stop
|
|
`, envVarPrefix, envVarPrefix)
|
|
}
|
|
|
|
func executeInteractive(remoteConsole client.Client) error {
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
fmt.Println("To quit the session type 'exit'.")
|
|
for scanner.Scan() {
|
|
fmt.Print("> ")
|
|
cmd := scanner.Text()
|
|
if cmd == "exit" {
|
|
return nil
|
|
}
|
|
resp, err := execute(cmd, remoteConsole)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println(resp)
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
return fmt.Errorf("reading standard input: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func execute(cmd string, client client.Client) (string, error) {
|
|
response, err := client.Exec(cmd)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to execute command: %w", err)
|
|
}
|
|
|
|
return string(response), nil
|
|
}
|