starting sqlite rewrite
- adding db connector - starting rewrite of commands - WIP
This commit is contained in:
parent
58ece42142
commit
77bb3166c4
@ -119,4 +119,11 @@ mctl utilizes [govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
|
||||
<br />
|
||||
|
||||
# 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
|
@ -1,11 +1,11 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"code.jakeyoungdev.com/jake/mctl/cryptography"
|
||||
"code.jakeyoungdev.com/jake/mctl/database"
|
||||
"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
|
||||
func New() (*Client, error) {
|
||||
//grab saved credentials
|
||||
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))
|
||||
func New(name string) (*Client, error) {
|
||||
db, err := database.New()
|
||||
if err != nil {
|
||||
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
|
||||
cli := mcr.NewClient(server, mcr.WithPort(port))
|
||||
err = cli.Connect(string(pt))
|
||||
cli := mcr.NewClient(srv.Server, mcr.WithPort(srv.Port))
|
||||
err = cli.Connect(string(p))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
27
cmd/clear.go
27
cmd/clear.go
@ -5,36 +5,25 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"code.jakeyoungdev.com/jake/mctl/models"
|
||||
"code.jakeyoungdev.com/jake/mctl/database"
|
||||
"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`,
|
||||
Long: `Clears all configuration values for mctl. [WARNING] all server configuration will be lost`,
|
||||
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)
|
||||
|
||||
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")
|
||||
}
|
||||
fmt.Println("Configuration is cleared, the 'config' command must be run again.")
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -4,26 +4,26 @@ Copyright © 2025 Jake jake.young.dev@gmail.com
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"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/viper"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
var (
|
||||
cfgserver string
|
||||
cfgport int
|
||||
cfgname string
|
||||
)
|
||||
|
||||
// configCmd represents the config command
|
||||
var configCmd = &cobra.Command{
|
||||
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",
|
||||
Long: `Creates the .mctl file in the user home directory
|
||||
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()))
|
||||
cobra.CheckErr(err)
|
||||
|
||||
//generate and apply random nonce
|
||||
nonce := make([]byte, 12)
|
||||
_, err = io.ReadFull(rand.Reader, nonce)
|
||||
db, err := database.New()
|
||||
cobra.CheckErr(err)
|
||||
viper.Set("nonce", string(nonce))
|
||||
defer db.Close()
|
||||
|
||||
//encrypt password
|
||||
ciphert, err := cryptography.EncryptPassword(ps)
|
||||
err = db.Init()
|
||||
cobra.CheckErr(err)
|
||||
|
||||
//update config file with new values
|
||||
viper.Set("server", cfgserver)
|
||||
viper.Set("password", string(ciphert))
|
||||
viper.Set("port", cfgport)
|
||||
err = viper.WriteConfig()
|
||||
err = db.SaveServer(model.Server{
|
||||
Name: cfgname,
|
||||
Server: cfgserver,
|
||||
Port: cfgport,
|
||||
Password: base64.StdEncoding.EncodeToString(ps),
|
||||
})
|
||||
cobra.CheckErr(err)
|
||||
fmt.Println()
|
||||
fmt.Println("Config file updated!")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
initConfig()
|
||||
configCmd.Flags().StringVarP(&cfgserver, "server", "s", "", "server address")
|
||||
err := configCmd.MarkFlagRequired("server")
|
||||
cobra.CheckErr(err)
|
||||
configCmd.Flags().IntVarP(&cfgport, "port", "p", 0, "server rcon port")
|
||||
err = configCmd.MarkFlagRequired("port")
|
||||
cobra.CheckErr(err)
|
||||
configCmd.Flags().StringVarP(&cfgname, "name", "n", "", "server alias")
|
||||
err = configCmd.MarkFlagRequired("name")
|
||||
cobra.CheckErr(err)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,10 @@ package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"code.jakeyoungdev.com/jake/mctl/database"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// deleteCmd represents the delete command
|
||||
@ -17,13 +18,13 @@ var deleteCmd = &cobra.Command{
|
||||
Short: "Delete a saved command",
|
||||
Long: `Deletes a command stored using the save command`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if viper.IsSet("customcmd") {
|
||||
cmdMap := viper.Get("customcmd").(map[string]any)
|
||||
delete(cmdMap, args[0])
|
||||
viper.Set("customcmd", cmdMap)
|
||||
err := viper.WriteConfig()
|
||||
cobra.CheckErr(err)
|
||||
}
|
||||
db, err := database.New()
|
||||
cobra.CheckErr(err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.DeleteCmd(args[0])
|
||||
cobra.CheckErr(err)
|
||||
fmt.Println("Command deleted")
|
||||
},
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
|
44
cmd/login.go
44
cmd/login.go
@ -10,28 +10,36 @@ import (
|
||||
"os"
|
||||
|
||||
"code.jakeyoungdev.com/jake/mctl/client"
|
||||
"code.jakeyoungdev.com/jake/mctl/database"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var (
|
||||
name string
|
||||
)
|
||||
|
||||
// loginCmd represents the login command
|
||||
var loginCmd = &cobra.Command{
|
||||
Use: "login",
|
||||
Example: "mctl login",
|
||||
Example: "mctl login <name>",
|
||||
SilenceUsage: true,
|
||||
Short: "Login to server and send commands",
|
||||
Long: `Login to server using saved config and enter command loop
|
||||
sending commands to server and printing the response.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
//grab saved credentials
|
||||
server := viper.Get("server").(string)
|
||||
cli, err := client.New()
|
||||
server := args[0]
|
||||
cli, err := client.New(server)
|
||||
cobra.CheckErr(err)
|
||||
defer cli.Close()
|
||||
|
||||
//start command loop
|
||||
fmt.Println("Connected! Type 'mctl' to close")
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
|
||||
db, err := database.New()
|
||||
cobra.CheckErr(err)
|
||||
defer db.Close()
|
||||
|
||||
var runningCmd string
|
||||
for runningCmd != "mctl" {
|
||||
fmt.Printf("RCON@%s /> ", server)
|
||||
@ -48,6 +56,11 @@ var loginCmd = &cobra.Command{
|
||||
break
|
||||
}
|
||||
|
||||
if runningCmd == ".run" {
|
||||
}
|
||||
//hmm this gets weird af tbh
|
||||
dbcmd, err := db.GetCmd(runningCmd)
|
||||
|
||||
res, err := cli.Command(runningCmd)
|
||||
cobra.CheckErr(err)
|
||||
fmt.Printf("\n%s\n", res)
|
||||
@ -57,9 +70,24 @@ var loginCmd = &cobra.Command{
|
||||
fmt.Printf("Disconnected from %s\n", server)
|
||||
},
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
//ensure config command has been run
|
||||
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")
|
||||
if len(args) == 0 {
|
||||
return errors.New("must specify which server to login to")
|
||||
}
|
||||
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
|
||||
|
15
cmd/run.go
15
cmd/run.go
@ -4,11 +4,13 @@ Copyright © 2025 Jake jake.young.dev@gmail.com
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.jakeyoungdev.com/jake/mctl/client"
|
||||
"code.jakeyoungdev.com/jake/mctl/database"
|
||||
"github.com/spf13/cobra"
|
||||
"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
|
||||
printing the response`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cm := viper.Get("customcmd").(map[string]any)
|
||||
//is this an existing command
|
||||
cmdRun, ok := cm[args[0]]
|
||||
if !ok {
|
||||
db, err := database.New()
|
||||
cobra.CheckErr(err)
|
||||
defer db.Close()
|
||||
|
||||
sc, err := db.GetCmd(args[0])
|
||||
if err == sql.ErrNoRows {
|
||||
fmt.Printf("command %s not found", args[0])
|
||||
return
|
||||
}
|
||||
cobra.CheckErr(err)
|
||||
|
||||
//convert arguments to interface
|
||||
var nargs []any
|
||||
@ -37,7 +42,7 @@ var runCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
//inject arguments
|
||||
fixed := fmt.Sprintf(cmdRun.(string), nargs...)
|
||||
fixed := fmt.Sprintf(sc, nargs...)
|
||||
fmt.Printf("Running saved command %s\n", fixed)
|
||||
|
||||
//create client and send command
|
||||
|
19
cmd/save.go
19
cmd/save.go
@ -9,8 +9,8 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"code.jakeyoungdev.com/jake/mctl/database"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// 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
|
||||
used as a wildcard to be injected when running the command`,
|
||||
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: ")
|
||||
sc := bufio.NewScanner(os.Stdin)
|
||||
if sc.Scan() {
|
||||
txt := sc.Text()
|
||||
if txt != "" {
|
||||
var cmdMap map[string]any
|
||||
cm := viper.Get("customcmd")
|
||||
if cmdMap == nil {
|
||||
cmdMap = make(map[string]any, 0)
|
||||
} else {
|
||||
cmdMap = cm.(map[string]any)
|
||||
}
|
||||
cmdMap[args[0]] = txt
|
||||
viper.Set("customcmd", cmdMap)
|
||||
err := viper.WriteConfig()
|
||||
db, err := database.New()
|
||||
cobra.CheckErr(err)
|
||||
defer db.Close()
|
||||
|
||||
err = db.SaveCmd(args[0], txt)
|
||||
cobra.CheckErr(err)
|
||||
fmt.Println("\nSaved!")
|
||||
}
|
||||
|
39
cmd/view.go
39
cmd/view.go
@ -8,8 +8,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.jakeyoungdev.com/jake/mctl/database"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// viewCmd represents the view command
|
||||
@ -19,32 +19,29 @@ var viewCmd = &cobra.Command{
|
||||
Short: "View saved commands",
|
||||
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) {
|
||||
var cm map[string]any
|
||||
cmdMap := viper.Get("customcmd")
|
||||
if cmdMap == nil {
|
||||
fmt.Println("no custom commands found")
|
||||
return
|
||||
}
|
||||
|
||||
cm = cmdMap.(map[string]any)
|
||||
|
||||
db, err := database.New()
|
||||
cobra.CheckErr(err)
|
||||
defer db.Close()
|
||||
if strings.EqualFold(args[0], "all") {
|
||||
//show all commands
|
||||
cmds, err := db.GetAllCmds()
|
||||
cobra.CheckErr(err)
|
||||
|
||||
fmt.Println("\nCommands: ")
|
||||
for k, v := range cm {
|
||||
fmt.Printf("%s - %s\n", k, v)
|
||||
for _, c := range cmds {
|
||||
fmt.Printf("%s - %s\n", c.Name, c.Command)
|
||||
}
|
||||
fmt.Println()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
cmds, err := db.GetCmd(args[0])
|
||||
cobra.CheckErr(err)
|
||||
|
||||
custom, ok := cm[args[0]]
|
||||
if !ok {
|
||||
fmt.Println("command not found")
|
||||
return
|
||||
}
|
||||
if cmds == "" {
|
||||
fmt.Println("Command not found")
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Command: %s\n", custom.(string))
|
||||
fmt.Printf("Command: %s\n", cmds)
|
||||
}
|
||||
},
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
|
250
database/commands.go
Normal file
250
database/commands.go
Normal 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
8
go.mod
@ -4,6 +4,8 @@ go 1.24.2
|
||||
|
||||
require (
|
||||
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/viper v1.20.1
|
||||
golang.org/x/term v0.31.0
|
||||
@ -13,6 +15,7 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // 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/sagikazarmark/locafero v0.7.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/pflag v1.0.6 // 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/multierr v1.9.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
26
go.sum
26
go.sum
@ -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/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=
|
||||
@ -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/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
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/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
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/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
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/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/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
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/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
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/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
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/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
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=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
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/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
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 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
16
model/data.go
Normal file
16
model/data.go
Normal 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"`
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
package models
|
||||
|
||||
//list of all fields kept in config file
|
||||
var ConfigFields = [6]string{"customcmd", "device", "nonce", "port", "server", "password"}
|
Loading…
x
Reference in New Issue
Block a user