Compare commits
12 Commits
v0.3.0
...
58ece42142
Author | SHA1 | Date | |
---|---|---|---|
58ece42142 | |||
49c508aae7 | |||
dcfad2dfee | |||
5b6ddc71cf | |||
f8282c3676 | |||
386a766185 | |||
26c50085d6 | |||
13d3b2cef3 | |||
4100762986 | |||
a3527d3388 | |||
35fb9fc270 | |||
6fe91f816b |
17
.gitea/workflows/security.yaml
Normal file
17
.gitea/workflows/security.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
name: "code scans"
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
tags:
|
||||||
|
- v*
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
scans:
|
||||||
|
runs-on: fire
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: "dependency scan and static code analysis"
|
||||||
|
uses: https://code.jakeyoungdev.com/actions/donotpassgo@v1.1.0
|
61
README.md
61
README.md
@@ -1,16 +1,26 @@
|
|||||||
# mctl
|
# mctl
|
||||||
mctl is a terminal-friendly remote connection client
|
mctl is a terminal-friendly remote console client
|
||||||
|
|
||||||
## Installation
|
# Index
|
||||||
|
1. [Installation](#installation)
|
||||||
|
2. [Setup](#setup)
|
||||||
|
3. [Documentation](#documentation)
|
||||||
|
4. [Security](#security)
|
||||||
|
5. [Development](#development)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
# Installation
|
||||||
Install mctl using golang
|
Install mctl using golang
|
||||||
```bash
|
```bash
|
||||||
go install code.jakeyoungdev.com/jake/mctl@main #it is recommended to use a tagged version
|
go install code.jakeyoungdev.com/jake/mctl@main #it is recommended to use a tagged version
|
||||||
```
|
```
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
## Setup
|
# Setup
|
||||||
### Configuring mctl
|
### Configuring mctl
|
||||||
mctl requires a one-time setup via the 'config' command before interacting with any servers, password is entered securely from the terminal
|
mctl requires a one-time setup via the 'config' command before interacting with any servers, password is entered securely from the terminal and encrypted
|
||||||
```bash
|
```bash
|
||||||
mctl config -s <serveraddress> -p <rconport>
|
mctl config -s <serveraddress> -p <rconport>
|
||||||
```
|
```
|
||||||
@@ -23,7 +33,7 @@ mctl login #makes auth request to server with saved password
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Sending commands
|
### Sending commands
|
||||||
If login is successful the app will enter the command loop, which allows commands to be sent directly to the server until 'mctl' is sent. Commands are sent as-is to the server, there is no validation of command syntax within mctl
|
If login is successful the app will enter the command loop, which allows commands to be sent directly to the server. Commands are sent as-is to the server, there is no validation of command syntax within mctl
|
||||||
```
|
```
|
||||||
Logging into X.X.X.X on port 61695
|
Logging into X.X.X.X on port 61695
|
||||||
Connected! Type 'mctl' to close
|
Connected! Type 'mctl' to close
|
||||||
@@ -33,7 +43,7 @@ There are 0 of a max of 20 players online:
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Saving commands
|
### Saving commands
|
||||||
Commands can be saved under an alias for quick execution later, saved commands can contain placeholders '%s' that can be populated at runtime to allow for commands with unique runtime args to still be saved:
|
Commands can be saved under an alias for quick execution later, saved commands can contain placeholders '%s' that can be populated at runtime to allow for commands with unique runtime args to still be saved, see [example](#saving-and-running-example) for more:
|
||||||
```bash
|
```bash
|
||||||
mctl save <name>
|
mctl save <name>
|
||||||
```
|
```
|
||||||
@@ -43,6 +53,10 @@ Saved commands can be viewed with:
|
|||||||
```bash
|
```bash
|
||||||
mctl view <name>
|
mctl view <name>
|
||||||
```
|
```
|
||||||
|
All saved commands can be viewed with:
|
||||||
|
```bash
|
||||||
|
mctl view all
|
||||||
|
```
|
||||||
|
|
||||||
### Running saved commands
|
### Running saved commands
|
||||||
Commands that have been saved can be run with:
|
Commands that have been saved can be run with:
|
||||||
@@ -71,7 +85,16 @@ Commands can be deleted with:
|
|||||||
mctl delete <name>
|
mctl delete <name>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Documentation
|
### Clear configuration file
|
||||||
|
To clear all fields from the configuration file use:
|
||||||
|
```bash
|
||||||
|
#CAUTION: If the config file is cleared all data previously saved will be lost forever
|
||||||
|
mctl clear
|
||||||
|
```
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
# Documentation
|
||||||
### Commands
|
### Commands
|
||||||
|Command|Description|
|
|Command|Description|
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -81,19 +104,19 @@ mctl delete <name>
|
|||||||
|view \<name>|displays saved command|
|
|view \<name>|displays saved command|
|
||||||
|delete \<name>|deletes saved command|
|
|delete \<name>|deletes saved command|
|
||||||
|run \<name> args...|runs saved command filling placeholders with supplied args|
|
|run \<name> args...|runs saved command filling placeholders with supplied args|
|
||||||
|
|clear|clears config file|
|
||||||
### Flags
|
|
||||||
#### config
|
|
||||||
|Flag|Shorthand|Required|Description|
|
|
||||||
|---|---|---|---|
|
|
||||||
|port|p|yes|RCon port|
|
|
||||||
|server|s|yes|RCon address|
|
|
||||||
|
|
||||||
### Configuration file
|
### Configuration file
|
||||||
All configuration data will be kept in /home/.mctl.yaml or C:\\Users\\username\\.mctl.yaml, passwords are encrypted for an added layer of security
|
All configuration data will be kept in the home directory and any sensitive data is encrypted for added security
|
||||||
|
|
||||||
## Security
|
<br />
|
||||||
RCon is an inherently insecure protocol, passwords are sent in plaintext and, if possible, the port should not be exposed to the internet. It is best to keep these connections local or over a VPN
|
|
||||||
|
|
||||||
## Development
|
# Security
|
||||||
this repo is currently in heavy development and may encounter breaking changes, use a tag to prevent any surprises
|
RCon is an inherently insecure protocol, passwords are sent in plaintext and, if possible, the port should not be exposed to the internet. It is best to keep these connections local or over a VPN.
|
||||||
|
|
||||||
|
mctl utilizes [govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck) and [gosec](https://github.com/securego/gosec) in workflows to ensure quality, secure code is being pushed. These workflow steps must pass before a PR will be accepted
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
# Development
|
||||||
|
this repo is currently in development and may encounter breaking changes, use a tag to prevent any surprises
|
@@ -14,7 +14,7 @@ import (
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
cli *mcr.Client
|
cli mcr.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
type IClient interface {
|
type IClient interface {
|
||||||
|
43
cmd/clear.go
Normal file
43
cmd/clear.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
Copyright © 2025 Jake jake.young.dev@gmail.com
|
||||||
|
*/
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"code.jakeyoungdev.com/jake/mctl/models"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// clearCmd represents the clear command
|
||||||
|
var clearCmd = &cobra.Command{
|
||||||
|
Use: "clear",
|
||||||
|
Short: "Clear config file",
|
||||||
|
Long: `Clears all configuration values for mctl, all server configuration will be lost`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
home, err := os.UserHomeDir()
|
||||||
|
cobra.CheckErr(err)
|
||||||
|
|
||||||
|
viper.AddConfigPath(home)
|
||||||
|
viper.SetConfigType("yaml")
|
||||||
|
viper.SetConfigName(".mctl")
|
||||||
|
|
||||||
|
err = viper.ReadInConfig()
|
||||||
|
if err == nil {
|
||||||
|
//clear values if file exists
|
||||||
|
for _, v := range models.ConfigFields {
|
||||||
|
viper.Set(v, "")
|
||||||
|
}
|
||||||
|
err := viper.WriteConfig()
|
||||||
|
cobra.CheckErr(err)
|
||||||
|
fmt.Println("Config file cleared, use 'config' command to re-populate it")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(clearCmd)
|
||||||
|
}
|
@@ -48,7 +48,8 @@ var configCmd = &cobra.Command{
|
|||||||
viper.Set("server", cfgserver)
|
viper.Set("server", cfgserver)
|
||||||
viper.Set("password", string(ciphert))
|
viper.Set("password", string(ciphert))
|
||||||
viper.Set("port", cfgport)
|
viper.Set("port", cfgport)
|
||||||
viper.WriteConfig()
|
err = viper.WriteConfig()
|
||||||
|
cobra.CheckErr(err)
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("Config file updated!")
|
fmt.Println("Config file updated!")
|
||||||
},
|
},
|
||||||
@@ -57,9 +58,11 @@ var configCmd = &cobra.Command{
|
|||||||
func init() {
|
func init() {
|
||||||
initConfig()
|
initConfig()
|
||||||
configCmd.Flags().StringVarP(&cfgserver, "server", "s", "", "server address")
|
configCmd.Flags().StringVarP(&cfgserver, "server", "s", "", "server address")
|
||||||
configCmd.MarkFlagRequired("server")
|
err := configCmd.MarkFlagRequired("server")
|
||||||
|
cobra.CheckErr(err)
|
||||||
configCmd.Flags().IntVarP(&cfgport, "port", "p", 0, "server rcon port")
|
configCmd.Flags().IntVarP(&cfgport, "port", "p", 0, "server rcon port")
|
||||||
configCmd.MarkFlagRequired("port")
|
err = configCmd.MarkFlagRequired("port")
|
||||||
|
cobra.CheckErr(err)
|
||||||
rootCmd.AddCommand(configCmd)
|
rootCmd.AddCommand(configCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,9 +75,9 @@ func initConfig() {
|
|||||||
viper.SetConfigType("yaml")
|
viper.SetConfigType("yaml")
|
||||||
viper.SetConfigName(".mctl")
|
viper.SetConfigName(".mctl")
|
||||||
viper.AutomaticEnv()
|
viper.AutomaticEnv()
|
||||||
viper.ReadInConfig()
|
err = viper.ReadInConfig()
|
||||||
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
if err != nil {
|
||||||
//file does not exist, create it
|
//file does not exist, create it
|
||||||
viper.Set("server", cfgserver)
|
viper.Set("server", cfgserver)
|
||||||
viper.Set("password", "")
|
viper.Set("password", "")
|
||||||
@@ -92,6 +95,7 @@ func initConfig() {
|
|||||||
//write config
|
//write config
|
||||||
viper.Set("customcmd", cmdMap)
|
viper.Set("customcmd", cmdMap)
|
||||||
viper.Set("device", string(uu))
|
viper.Set("device", string(uu))
|
||||||
viper.SafeWriteConfig()
|
err = viper.SafeWriteConfig()
|
||||||
|
cobra.CheckErr(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,16 +17,13 @@ var deleteCmd = &cobra.Command{
|
|||||||
Short: "Delete a saved command",
|
Short: "Delete a saved command",
|
||||||
Long: `Deletes a command stored using the save command`,
|
Long: `Deletes a command stored using the save command`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
var cm map[string]any
|
if viper.IsSet("customcmd") {
|
||||||
cmdMap := viper.Get("customcmd")
|
cmdMap := viper.Get("customcmd").(map[string]any)
|
||||||
if cmdMap == nil {
|
delete(cmdMap, args[0])
|
||||||
cm = make(map[string]any, 0)
|
|
||||||
} else {
|
|
||||||
cm = cmdMap.(map[string]any)
|
|
||||||
}
|
|
||||||
delete(cm, args[0])
|
|
||||||
viper.Set("customcmd", cmdMap)
|
viper.Set("customcmd", cmdMap)
|
||||||
viper.WriteConfig()
|
err := viper.WriteConfig()
|
||||||
|
cobra.CheckErr(err)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
|
@@ -58,9 +58,10 @@ var loginCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
//ensure config command has been run
|
//ensure config command has been run
|
||||||
if viper.Get("server") == "" || viper.Get("password") == "" || viper.Get("port") == 0 {
|
if !viper.IsSet("server") || !viper.IsSet("password") || !viper.IsSet("port") {
|
||||||
return errors.New("the 'config' command must be run before you can interact with servers")
|
return errors.New("the 'config' command must be run before you can interact with servers")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,7 @@ var rootCmd = &cobra.Command{
|
|||||||
Use: "mctl",
|
Use: "mctl",
|
||||||
Short: "A remote console client",
|
Short: "A remote console client",
|
||||||
Long: `mctl is a terminal-friendly remote console client made to manage game servers.`,
|
Long: `mctl is a terminal-friendly remote console client made to manage game servers.`,
|
||||||
Version: "v0.2.0",
|
Version: "v0.3.4",
|
||||||
// Run: func(cmd *cobra.Command, args []string) { },
|
// Run: func(cmd *cobra.Command, args []string) { },
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,5 +28,7 @@ func Execute() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
rootCmd.CompletionOptions = cobra.CompletionOptions{
|
||||||
|
DisableDefaultCmd: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
17
cmd/run.go
17
cmd/run.go
@@ -22,14 +22,7 @@ var runCmd = &cobra.Command{
|
|||||||
Long: `Loads a saved command, injects the supplied arguments into the command, and sends the command to the remove server
|
Long: `Loads a saved command, injects the supplied arguments into the command, and sends the command to the remove server
|
||||||
printing the response`,
|
printing the response`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
//check for command map
|
cm := viper.Get("customcmd").(map[string]any)
|
||||||
var cm map[string]any
|
|
||||||
cmdMap := viper.Get("customcmd")
|
|
||||||
if cmdMap == nil {
|
|
||||||
cm = make(map[string]any, 0)
|
|
||||||
} else {
|
|
||||||
cm = cmdMap.(map[string]any)
|
|
||||||
}
|
|
||||||
//is this an existing command
|
//is this an existing command
|
||||||
cmdRun, ok := cm[args[0]]
|
cmdRun, ok := cm[args[0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -58,11 +51,15 @@ var runCmd = &cobra.Command{
|
|||||||
fmt.Println(res)
|
fmt.Println(res)
|
||||||
},
|
},
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
//ensure configuration has been setup
|
//ensure config command has been run
|
||||||
if viper.Get("server") == "" || viper.Get("password") == "" || viper.Get("port") == 0 {
|
if !viper.IsSet("server") || !viper.IsSet("password") || !viper.IsSet("port") {
|
||||||
return errors.New("the 'config' command must be run before you can interact with servers")
|
return errors.New("the 'config' command must be run before you can interact with servers")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !viper.IsSet("customcmd") {
|
||||||
|
return errors.New("no saved commands to run")
|
||||||
|
}
|
||||||
|
|
||||||
//ensure we have a command name
|
//ensure we have a command name
|
||||||
al := len(args)
|
al := len(args)
|
||||||
if al == 0 {
|
if al == 0 {
|
||||||
|
@@ -36,7 +36,8 @@ var saveCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
cmdMap[args[0]] = txt
|
cmdMap[args[0]] = txt
|
||||||
viper.Set("customcmd", cmdMap)
|
viper.Set("customcmd", cmdMap)
|
||||||
viper.WriteConfig()
|
err := viper.WriteConfig()
|
||||||
|
cobra.CheckErr(err)
|
||||||
fmt.Println("\nSaved!")
|
fmt.Println("\nSaved!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
cmd/view.go
16
cmd/view.go
@@ -6,6 +6,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@@ -16,7 +17,7 @@ var viewCmd = &cobra.Command{
|
|||||||
Use: "view <name>",
|
Use: "view <name>",
|
||||||
Example: "mctl view test",
|
Example: "mctl view test",
|
||||||
Short: "View saved commands",
|
Short: "View saved commands",
|
||||||
Long: `Load command using the supplied name and displays it in the terminal`,
|
Long: `Load command using the supplied name and displays it in the terminal, 'all' will list every saved command`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
var cm map[string]any
|
var cm map[string]any
|
||||||
cmdMap := viper.Get("customcmd")
|
cmdMap := viper.Get("customcmd")
|
||||||
@@ -26,13 +27,24 @@ var viewCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
cm = cmdMap.(map[string]any)
|
cm = cmdMap.(map[string]any)
|
||||||
|
|
||||||
|
if strings.EqualFold(args[0], "all") {
|
||||||
|
//show all commands
|
||||||
|
fmt.Println("\nCommands: ")
|
||||||
|
for k, v := range cm {
|
||||||
|
fmt.Printf("%s - %s\n", k, v)
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
custom, ok := cm[args[0]]
|
custom, ok := cm[args[0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Println("command not found")
|
fmt.Println("command not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Command: %s", custom.(string))
|
fmt.Printf("Command: %s\n", custom.(string))
|
||||||
},
|
},
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
|
@@ -21,7 +21,10 @@ func EncryptPassword(b []byte) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ct := aesg.Seal(nil, []byte(nonce), []byte(b), nil)
|
//adding #nosec trigger here since gosec interprets this as a hardcoded nonce value. The nonce is calculated using crypto/rand when the
|
||||||
|
//config command is ran and is pulled from memory when used any times after, for now we must prevent the scan from catching here until gosec
|
||||||
|
//is updated to account for this properly
|
||||||
|
ct := aesg.Seal(nil, []byte(nonce), []byte(b), nil) // #nosec
|
||||||
return ct, nil
|
return ct, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
go.mod
4
go.mod
@@ -1,9 +1,9 @@
|
|||||||
module code.jakeyoungdev.com/jake/mctl
|
module code.jakeyoungdev.com/jake/mctl
|
||||||
|
|
||||||
go 1.24.0
|
go 1.24.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/jake-young-dev/mcr v1.3.1
|
github.com/jake-young-dev/mcr v1.4.0
|
||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/cobra v1.9.1
|
||||||
github.com/spf13/viper v1.20.1
|
github.com/spf13/viper v1.20.1
|
||||||
golang.org/x/term v0.31.0
|
golang.org/x/term v0.31.0
|
||||||
|
2
go.sum
2
go.sum
@@ -14,6 +14,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
|
|||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jake-young-dev/mcr v1.3.1 h1:ELJsrJHwQsMiM09o+q8auUaiGXXX3DWIgh/TfZQc0B0=
|
github.com/jake-young-dev/mcr v1.3.1 h1:ELJsrJHwQsMiM09o+q8auUaiGXXX3DWIgh/TfZQc0B0=
|
||||||
github.com/jake-young-dev/mcr v1.3.1/go.mod h1:74yZHGf9h3tLUDUpInA17grKLrNp9lVesWvisCFCXKY=
|
github.com/jake-young-dev/mcr v1.3.1/go.mod h1:74yZHGf9h3tLUDUpInA17grKLrNp9lVesWvisCFCXKY=
|
||||||
|
github.com/jake-young-dev/mcr v1.4.0 h1:cXZImkfI8aNIiVPrONE6qP+nfblTGsD2iXpPKTcA25U=
|
||||||
|
github.com/jake-young-dev/mcr v1.4.0/go.mod h1:74yZHGf9h3tLUDUpInA17grKLrNp9lVesWvisCFCXKY=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
4
models/data.go
Normal file
4
models/data.go
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
//list of all fields kept in config file
|
||||||
|
var ConfigFields = [6]string{"customcmd", "device", "nonce", "port", "server", "password"}
|
Reference in New Issue
Block a user