starting sqlite rewrite

- adding db connector
- starting rewrite of commands
- WIP
This commit is contained in:
jake 2025-06-16 19:17:52 -04:00
parent 58ece42142
commit 77bb3166c4
14 changed files with 421 additions and 152 deletions

View File

@ -119,4 +119,11 @@ mctl utilizes [govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
<br /> <br />
# Development # Development
this repo is currently in development and may encounter breaking changes, use a tag to prevent any surprises this repo is currently in development and may encounter breaking changes, use a tag to prevent any surprises
# TODO
1. continue sqlite update
2. migrate the credentials to sqlite as well
3. login too
4. MCR client also has viper stuff, gut it
5. Since we are now using sqlite should we just encode the pwd and insert

View File

@ -1,11 +1,11 @@
package client package client
import ( import (
"encoding/base64"
"fmt" "fmt"
"code.jakeyoungdev.com/jake/mctl/cryptography" "code.jakeyoungdev.com/jake/mctl/database"
"github.com/jake-young-dev/mcr" "github.com/jake-young-dev/mcr"
"github.com/spf13/viper"
) )
/* /*
@ -23,22 +23,25 @@ type IClient interface {
} }
// creates a new mcr client using saved credentials and decrypted password // creates a new mcr client using saved credentials and decrypted password
func New() (*Client, error) { func New(name string) (*Client, error) {
//grab saved credentials db, err := database.New()
server := viper.Get("server").(string)
password := viper.Get("password").(string)
port := viper.Get("port").(int)
fmt.Printf("Logging into %s on port %d\n", server, port)
//decrypt password
pt, err := cryptography.DecryptPassword([]byte(password))
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer db.Close()
srv, err := db.GetServer(name)
if err != nil {
return nil, err
}
fmt.Printf("Logging into %s on port %d\n", srv.Server, srv.Port)
var p []byte
_, err = base64.StdEncoding.Decode(p, []byte(srv.Password))
//connect to game server //connect to game server
cli := mcr.NewClient(server, mcr.WithPort(port)) cli := mcr.NewClient(srv.Server, mcr.WithPort(srv.Port))
err = cli.Connect(string(pt)) err = cli.Connect(string(p))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -5,36 +5,25 @@ package cmd
import ( import (
"fmt" "fmt"
"os"
"code.jakeyoungdev.com/jake/mctl/models" "code.jakeyoungdev.com/jake/mctl/database"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
// clearCmd represents the clear command // clearCmd represents the clear command
var clearCmd = &cobra.Command{ var clearCmd = &cobra.Command{
Use: "clear", Use: "clear",
Short: "Clear config file", Short: "Clear config file",
Long: `Clears all configuration values for mctl, all server configuration will be lost`, Long: `Clears all configuration values for mctl. [WARNING] all server configuration will be lost`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
home, err := os.UserHomeDir() db, err := database.New()
cobra.CheckErr(err)
defer db.Close()
err = db.Destroy()
cobra.CheckErr(err) cobra.CheckErr(err)
viper.AddConfigPath(home) fmt.Println("Configuration is cleared, the 'config' command must be run again.")
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")
}
}, },
} }

View File

@ -4,26 +4,26 @@ Copyright © 2025 Jake jake.young.dev@gmail.com
package cmd package cmd
import ( import (
"crypto/rand" "encoding/base64"
"fmt" "fmt"
"io"
"os" "os"
"code.jakeyoungdev.com/jake/mctl/cryptography" "code.jakeyoungdev.com/jake/mctl/database"
"code.jakeyoungdev.com/jake/mctl/model"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/term" "golang.org/x/term"
) )
var ( var (
cfgserver string cfgserver string
cfgport int cfgport int
cfgname string
) )
// configCmd represents the config command // configCmd represents the config command
var configCmd = &cobra.Command{ var configCmd = &cobra.Command{
Use: "config", Use: "config",
Example: "mctl config -s x.x.x.x -p 61695", Example: "mctl config -n serverAlias -s x.x.x.x -p 61695",
Short: "Create and populate config file", Short: "Create and populate config file",
Long: `Creates the .mctl file in the user home directory Long: `Creates the .mctl file in the user home directory
populating it with the server address, rcon password, and populating it with the server address, rcon password, and
@ -34,68 +34,32 @@ var configCmd = &cobra.Command{
ps, err := term.ReadPassword(int(os.Stdin.Fd())) ps, err := term.ReadPassword(int(os.Stdin.Fd()))
cobra.CheckErr(err) cobra.CheckErr(err)
//generate and apply random nonce db, err := database.New()
nonce := make([]byte, 12)
_, err = io.ReadFull(rand.Reader, nonce)
cobra.CheckErr(err) cobra.CheckErr(err)
viper.Set("nonce", string(nonce)) defer db.Close()
//encrypt password err = db.Init()
ciphert, err := cryptography.EncryptPassword(ps)
cobra.CheckErr(err) cobra.CheckErr(err)
//update config file with new values err = db.SaveServer(model.Server{
viper.Set("server", cfgserver) Name: cfgname,
viper.Set("password", string(ciphert)) Server: cfgserver,
viper.Set("port", cfgport) Port: cfgport,
err = viper.WriteConfig() Password: base64.StdEncoding.EncodeToString(ps),
})
cobra.CheckErr(err) cobra.CheckErr(err)
fmt.Println()
fmt.Println("Config file updated!")
}, },
} }
func init() { func init() {
initConfig()
configCmd.Flags().StringVarP(&cfgserver, "server", "s", "", "server address") configCmd.Flags().StringVarP(&cfgserver, "server", "s", "", "server address")
err := configCmd.MarkFlagRequired("server") err := configCmd.MarkFlagRequired("server")
cobra.CheckErr(err) cobra.CheckErr(err)
configCmd.Flags().IntVarP(&cfgport, "port", "p", 0, "server rcon port") configCmd.Flags().IntVarP(&cfgport, "port", "p", 0, "server rcon port")
err = configCmd.MarkFlagRequired("port") err = configCmd.MarkFlagRequired("port")
cobra.CheckErr(err) cobra.CheckErr(err)
configCmd.Flags().StringVarP(&cfgname, "name", "n", "", "server alias")
err = configCmd.MarkFlagRequired("name")
cobra.CheckErr(err)
rootCmd.AddCommand(configCmd) rootCmd.AddCommand(configCmd)
} }
// init config sets viper config and checks for config file, creating it if it doesn't exist
func initConfig() {
home, err := os.UserHomeDir()
cobra.CheckErr(err)
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".mctl")
viper.AutomaticEnv()
err = viper.ReadInConfig()
if err != nil {
//file does not exist, create it
viper.Set("server", cfgserver)
viper.Set("password", "")
viper.Set("port", cfgport)
viper.Set("nonce", "")
//generate psuedo-random key
uu := make([]byte, 32)
_, err := rand.Read(uu)
cobra.CheckErr(err)
//create custom command map
cmdMap := make(map[string]any, 0)
//write config
viper.Set("customcmd", cmdMap)
viper.Set("device", string(uu))
err = viper.SafeWriteConfig()
cobra.CheckErr(err)
}
}

View File

@ -5,9 +5,10 @@ package cmd
import ( import (
"errors" "errors"
"fmt"
"code.jakeyoungdev.com/jake/mctl/database"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
// deleteCmd represents the delete command // deleteCmd represents the delete command
@ -17,13 +18,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) {
if viper.IsSet("customcmd") { db, err := database.New()
cmdMap := viper.Get("customcmd").(map[string]any) cobra.CheckErr(err)
delete(cmdMap, args[0]) defer db.Close()
viper.Set("customcmd", cmdMap)
err := viper.WriteConfig() err = db.DeleteCmd(args[0])
cobra.CheckErr(err) cobra.CheckErr(err)
} fmt.Println("Command deleted")
}, },
PreRunE: func(cmd *cobra.Command, args []string) error { PreRunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 { if len(args) == 0 {

View File

@ -10,28 +10,36 @@ import (
"os" "os"
"code.jakeyoungdev.com/jake/mctl/client" "code.jakeyoungdev.com/jake/mctl/client"
"code.jakeyoungdev.com/jake/mctl/database"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" )
var (
name string
) )
// loginCmd represents the login command // loginCmd represents the login command
var loginCmd = &cobra.Command{ var loginCmd = &cobra.Command{
Use: "login", Use: "login",
Example: "mctl login", Example: "mctl login <name>",
SilenceUsage: true, SilenceUsage: true,
Short: "Login to server and send commands", Short: "Login to server and send commands",
Long: `Login to server using saved config and enter command loop Long: `Login to server using saved config and enter command loop
sending commands to server and printing the response.`, sending commands to server and printing the response.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
//grab saved credentials server := args[0]
server := viper.Get("server").(string) cli, err := client.New(server)
cli, err := client.New()
cobra.CheckErr(err) cobra.CheckErr(err)
defer cli.Close() defer cli.Close()
//start command loop //start command loop
fmt.Println("Connected! Type 'mctl' to close") fmt.Println("Connected! Type 'mctl' to close")
scanner := bufio.NewScanner(os.Stdin) scanner := bufio.NewScanner(os.Stdin)
db, err := database.New()
cobra.CheckErr(err)
defer db.Close()
var runningCmd string var runningCmd string
for runningCmd != "mctl" { for runningCmd != "mctl" {
fmt.Printf("RCON@%s /> ", server) fmt.Printf("RCON@%s /> ", server)
@ -48,6 +56,11 @@ var loginCmd = &cobra.Command{
break break
} }
if runningCmd == ".run" {
}
//hmm this gets weird af tbh
dbcmd, err := db.GetCmd(runningCmd)
res, err := cli.Command(runningCmd) res, err := cli.Command(runningCmd)
cobra.CheckErr(err) cobra.CheckErr(err)
fmt.Printf("\n%s\n", res) fmt.Printf("\n%s\n", res)
@ -57,9 +70,24 @@ var loginCmd = &cobra.Command{
fmt.Printf("Disconnected from %s\n", server) fmt.Printf("Disconnected from %s\n", server)
}, },
PreRunE: func(cmd *cobra.Command, args []string) error { PreRunE: func(cmd *cobra.Command, args []string) error {
//ensure config command has been run if len(args) == 0 {
if !viper.IsSet("server") || !viper.IsSet("password") || !viper.IsSet("port") { return errors.New("must specify which server to login to")
return errors.New("the 'config' command must be run before you can interact with servers") }
srv := args[0]
db, err := database.New()
if err != nil {
return err
}
defer db.Close()
server, err := db.GetServer(srv)
if err != nil {
return err
}
if server.Name == "" {
return fmt.Errorf("server %s not found", server.Name)
} }
return nil return nil

View File

@ -4,11 +4,13 @@ Copyright © 2025 Jake jake.young.dev@gmail.com
package cmd package cmd
import ( import (
"database/sql"
"errors" "errors"
"fmt" "fmt"
"strings" "strings"
"code.jakeyoungdev.com/jake/mctl/client" "code.jakeyoungdev.com/jake/mctl/client"
"code.jakeyoungdev.com/jake/mctl/database"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
@ -22,13 +24,16 @@ 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) {
cm := viper.Get("customcmd").(map[string]any) db, err := database.New()
//is this an existing command cobra.CheckErr(err)
cmdRun, ok := cm[args[0]] defer db.Close()
if !ok {
sc, err := db.GetCmd(args[0])
if err == sql.ErrNoRows {
fmt.Printf("command %s not found", args[0]) fmt.Printf("command %s not found", args[0])
return return
} }
cobra.CheckErr(err)
//convert arguments to interface //convert arguments to interface
var nargs []any var nargs []any
@ -37,7 +42,7 @@ var runCmd = &cobra.Command{
} }
//inject arguments //inject arguments
fixed := fmt.Sprintf(cmdRun.(string), nargs...) fixed := fmt.Sprintf(sc, nargs...)
fmt.Printf("Running saved command %s\n", fixed) fmt.Printf("Running saved command %s\n", fixed)
//create client and send command //create client and send command

View File

@ -9,8 +9,8 @@ import (
"fmt" "fmt"
"os" "os"
"code.jakeyoungdev.com/jake/mctl/database"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
// saveCmd represents the save command // saveCmd represents the save command
@ -21,22 +21,17 @@ var saveCmd = &cobra.Command{
Long: `Saves supplied command using alias <name> to allow the command to be executed using the run command. The %s placeholder can be Long: `Saves supplied command using alias <name> to allow the command to be executed using the run command. The %s placeholder can be
used as a wildcard to be injected when running the command`, used as a wildcard to be injected when running the command`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Use %s as a wildcard in your command\n", "%s") //this is ugly, have to use printf to stop issues with compiler fmt.Printf("Use %s as a wildcard in your command\n", "%s") //this is ugly
fmt.Printf("Command: ") fmt.Printf("Command: ")
sc := bufio.NewScanner(os.Stdin) sc := bufio.NewScanner(os.Stdin)
if sc.Scan() { if sc.Scan() {
txt := sc.Text() txt := sc.Text()
if txt != "" { if txt != "" {
var cmdMap map[string]any db, err := database.New()
cm := viper.Get("customcmd") cobra.CheckErr(err)
if cmdMap == nil { defer db.Close()
cmdMap = make(map[string]any, 0)
} else { err = db.SaveCmd(args[0], txt)
cmdMap = cm.(map[string]any)
}
cmdMap[args[0]] = txt
viper.Set("customcmd", cmdMap)
err := viper.WriteConfig()
cobra.CheckErr(err) cobra.CheckErr(err)
fmt.Println("\nSaved!") fmt.Println("\nSaved!")
} }

View File

@ -8,8 +8,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"code.jakeyoungdev.com/jake/mctl/database"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
// viewCmd represents the view command // viewCmd represents the view command
@ -19,32 +19,29 @@ var viewCmd = &cobra.Command{
Short: "View saved commands", Short: "View saved commands",
Long: `Load command using the supplied name and displays it in the terminal, 'all' will list every saved command`, 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 db, err := database.New()
cmdMap := viper.Get("customcmd") cobra.CheckErr(err)
if cmdMap == nil { defer db.Close()
fmt.Println("no custom commands found")
return
}
cm = cmdMap.(map[string]any)
if strings.EqualFold(args[0], "all") { if strings.EqualFold(args[0], "all") {
//show all commands cmds, err := db.GetAllCmds()
cobra.CheckErr(err)
fmt.Println("\nCommands: ") fmt.Println("\nCommands: ")
for k, v := range cm { for _, c := range cmds {
fmt.Printf("%s - %s\n", k, v) fmt.Printf("%s - %s\n", c.Name, c.Command)
} }
fmt.Println() fmt.Println()
return } else {
} cmds, err := db.GetCmd(args[0])
cobra.CheckErr(err)
custom, ok := cm[args[0]] if cmds == "" {
if !ok { fmt.Println("Command not found")
fmt.Println("command not found") return
return }
}
fmt.Printf("Command: %s\n", custom.(string)) fmt.Printf("Command: %s\n", cmds)
}
}, },
PreRunE: func(cmd *cobra.Command, args []string) error { PreRunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 { if len(args) == 0 {

250
database/commands.go Normal file
View File

@ -0,0 +1,250 @@
package database
import (
"fmt"
"os"
"code.jakeyoungdev.com/jake/mctl/model"
"github.com/jmoiron/sqlx"
_ "github.com/ncruces/go-sqlite3/driver"
_ "github.com/ncruces/go-sqlite3/embed"
)
type database struct {
*sqlx.DB
}
type Database interface {
Init() error
Destroy() error
Close() error
//command methods
GetCmd(name string) (string, error)
GetAllCmds() ([]model.Command, error)
SaveCmd(name, cmd string) error
UpdateCmd(name, cmd string) error
DeleteCmd(name string) error
//server methods
GetServer(name string) (model.Server, error)
GetAllServers() ([]model.Server, error)
SaveServer(srv model.Server) error
UpdateServer(name, password string) error
DeleteServer(name string) error
}
func New() (Database, error) {
home, err := os.UserHomeDir()
if err != nil {
return nil, err
}
db, err := sqlx.Open("sqlite3", fmt.Sprintf("file:%s/.mctl", home))
if err != nil {
return nil, err
}
return &database{
db,
}, nil
}
func (d *database) Init() error {
query := `
CREATE TABLE IF NOT EXISTS commands(
name TEXT PRIMARY KEY,
command TEXT
)
CREATE TABLE IF NOT EXISTS servers(
name TEXT PRIMARY KEY,
server TEXT,
password TEXT,
port NUMBER
)
`
_, err := d.Exec(query)
return err
}
func (d *database) Destroy() error {
query := `
DROP TABLE commands
DROP TABLE servers
`
_, err := d.Exec(query)
return err
}
func (d *database) Close() error {
return d.Close()
}
func (d *database) GetCmd(name string) (string, error) {
query := `
SELECT
command
FROM
commands
WHERE
name = ?
`
var cmd string
err := d.QueryRowx(query, name).Scan(&cmd)
if err != nil {
return "", err
}
return name, nil
}
func (d *database) GetAllCmds() ([]model.Command, error) {
query := `
SELECT
name,
command
FROM
commands
`
rows, err := d.Queryx(query)
if err != nil {
return nil, err
}
defer rows.Close()
var res []model.Command
for rows.Next() {
var r model.Command
err := rows.StructScan(&r)
if err != nil {
return nil, err
}
res = append(res, r)
}
return res, nil
}
func (d *database) SaveCmd(name, cmd string) error {
query := `
INSERT INTO commands(name, command)
VALUES(?, ?)
`
_, err := d.Exec(query, name, cmd)
return err
}
func (d *database) UpdateCmd(name, cmd string) error {
query := `
UPDATE
commands
SET
cmd = ?
WHERE
name = ?
`
_, err := d.Exec(query, cmd, name)
return err
}
func (d *database) DeleteCmd(name string) error {
query := `
DELETE FROM commands
WHERE name = ?
`
_, err := d.Exec(query, name)
return err
}
func (d *database) GetServer(name string) (model.Server, error) {
query := `
SELECT
name,
server,
password,
port
FROM
servers
WHERE
name = ?
`
var s model.Server
err := d.QueryRowx(query, name).StructScan(&s)
if err != nil {
return model.Server{}, err
}
return s, nil
}
func (d *database) GetAllServers() ([]model.Server, error) {
query := `
SELECT
name,
server,
password,
port
FROM
servers
`
rows, err := d.Queryx(query)
if err != nil {
return nil, err
}
defer rows.Close()
var res []model.Server
for rows.Next() {
var r model.Server
err := rows.StructScan(&r)
if err != nil {
return nil, err
}
res = append(res, r)
}
return res, nil
}
func (d *database) SaveServer(srv model.Server) error {
query := `
INSERT INTO servers(name, server, password, port)
VALUES(?, ?, ?, ?)
`
_, err := d.Exec(query, srv.Name, srv.Server, srv.Password, srv.Port)
return err
}
// updates server password, if anymore fields need updated the entry should be deleted and recreated
func (d *database) UpdateServer(name, password string) error {
query := `
UPDATE servers
SET
password = ?
WHERE
name = ?
`
_, err := d.Exec(query, password, name)
return err
}
func (d *database) DeleteServer(name string) error {
query := `
DELETE FROM servers
WHERE
name = ?
`
_, err := d.Exec(query, name)
return err
}

8
go.mod
View File

@ -4,6 +4,8 @@ go 1.24.2
require ( require (
github.com/jake-young-dev/mcr v1.4.0 github.com/jake-young-dev/mcr v1.4.0
github.com/jmoiron/sqlx v1.4.0
github.com/ncruces/go-sqlite3 v0.26.1
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
@ -13,6 +15,7 @@ require (
github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ncruces/julianday v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect
@ -20,9 +23,10 @@ require (
github.com/spf13/cast v1.7.1 // indirect github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/subosito/gotenv v1.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect
golang.org/x/sys v0.32.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/text v0.26.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

26
go.sum
View File

@ -1,3 +1,5 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -6,20 +8,30 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
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/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 h1:cXZImkfI8aNIiVPrONE6qP+nfblTGsD2iXpPKTcA25U=
github.com/jake-young-dev/mcr v1.4.0/go.mod h1:74yZHGf9h3tLUDUpInA17grKLrNp9lVesWvisCFCXKY= github.com/jake-young-dev/mcr v1.4.0/go.mod h1:74yZHGf9h3tLUDUpInA17grKLrNp9lVesWvisCFCXKY=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
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=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/ncruces/go-sqlite3 v0.26.1 h1:lBXmbmucH1Bsj57NUQR6T84UoMN7jnNImhF+ibEITJU=
github.com/ncruces/go-sqlite3 v0.26.1/go.mod h1:XFTPtFIo1DmGCh+XVP8KGn9b/o2f+z0WZuT09x2N6eo=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -47,16 +59,18 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

16
model/data.go Normal file
View File

@ -0,0 +1,16 @@
package model
//list of all fields kept in config file
// var ConfigFields = [6]string{"customcmd", "device", "nonce", "port", "server", "password"}
type Command struct {
Name string `db:"name"`
Command string `db:"command"`
}
type Server struct {
Name string `db:"name"`
Server string `db:"server"`
Password string `db:"password"`
Port int `db:"port"`
}

View File

@ -1,4 +0,0 @@
package models
//list of all fields kept in config file
var ConfigFields = [6]string{"customcmd", "device", "nonce", "port", "server", "password"}