From 5e91839d84c16dc241ad8aa530ad890c10befddc Mon Sep 17 00:00:00 2001 From: CMarink Date: Sat, 24 May 2025 08:49:02 -0700 Subject: [PATCH] Implemented go-flags parser Instead of manually parsing commands, I implemented the smarter go-flags parser from: https://github.com/jessevdk/go-flags --- go.mod | 3 +- go.sum | 4 ++ jcliStart.go | 129 +++++++++++++++++++++++++++++++++------------------ 3 files changed, 89 insertions(+), 47 deletions(-) diff --git a/go.mod b/go.mod index 22d4a1f..4c3fb48 100644 --- a/go.mod +++ b/go.mod @@ -9,10 +9,11 @@ require ( github.com/go-openapi/errors v0.22.0 // indirect github.com/go-openapi/strfmt v0.23.0 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/jessevdk/go-flags v1.6.1 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/sys v0.21.0 // indirect ) diff --git a/go.sum b/go.sum index db6b026..eb03dc5 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo= github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= +github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= +github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -28,5 +30,7 @@ go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/jcliStart.go b/jcliStart.go index 63fde85..f2d10e3 100644 --- a/jcliStart.go +++ b/jcliStart.go @@ -5,6 +5,8 @@ import ( "fmt" "os" "strings" + + "github.com/jessevdk/go-flags" ) func printError(errStr error) { @@ -13,18 +15,87 @@ func printError(errStr error) { } } +var token string + +type LoginCommand struct{} + +func (c *LoginCommand) Execute(args []string) error { + return login() +} + +type ProjectsCommand struct{} + +func (c *ProjectsCommand) Execute(args []string) error { + switch len(args) { + case 0: + return projects(token) + case 1: + return projectsName(token, args[0]) + case 2: + if strings.ToLower(args[1]) == "sessions" { + return projectSessions(token, args[0]) + } + return fmt.Errorf("usage: projects sessions") + case 3: + return projectSessionId(token, args[0], args[2]) + default: + return fmt.Errorf("invalid usage of 'projects'") + } +} + +type GetCommand struct{} + +func (c *GetCommand) Execute(args []string) error { + if len(args) < 1 { + return fmt.Errorf("missing endpoint for get command") + } + return apiGet(args[0], token) +} + +type GameGetCommand struct{} + +func (c *GameGetCommand) Execute(args []string) error { + if len(args) < 2 { + return fmt.Errorf("usage: game-get ") + } + gameToken, err := getGameUserToken(args[0], token) + if err != nil { + return fmt.Errorf("failed to get game token: %v", err) + } + return apiGet(args[1], gameToken) +} + +type HelpCommand struct{} + +func (c *HelpCommand) Execute(args []string) error { + input := "help" + if len(args) > 0 { + input += " " + strings.Join(args, " ") + } + help(input) + return nil +} + +type Command struct { + Login LoginCommand `command:"login" description:"Log in to the system"` + Projects ProjectsCommand `command:"projects" description:"Manage projects"` + Get GetCommand `command:"get" description:"Call an API GET endpoint"` + GameGet GameGetCommand `command:"game-get" description:"Call an API GET endpoint as a game user"` + Help HelpCommand `command:"help" description:"Show help"` +} + func main() { // Step 1: Request Device Code fmt.Println("Welcome to the JamLaunch CLI!") fmt.Print("Checking token...") - result, token := loadToken() + result, tok := loadToken() if !result { fmt.Println("\033[91mToken not found or invalid! User must authenticate again.\033[0m") var err error - token, err = getDevToken() + tok, err = getDevToken() if err != nil { fmt.Printf("\033[31mFailed to get tokens: %v\n - exiting...\033[0m\n", err) } @@ -32,10 +103,15 @@ func main() { fmt.Printf("\033[92mLogin successful!\033[0m\n") } + token = tok + reader := bufio.NewReader(os.Stdin) fmt.Println("Type your message below. Type 'exit' to quit.") + var cmd Command + parser := flags.NewParser(&cmd, flags.None) + for { // Display a prompt fmt.Print("> ") @@ -50,53 +126,14 @@ func main() { // Trim whitespace input = strings.TrimSpace(input) - if strings.ToLower(input) == "login" { - err = login() - - printError(err) - } else if len(input) >= 8 && strings.ToLower(input[:8]) == "projects" { - parts := strings.Fields(input) - if len(parts) == 1 && strings.ToLower(parts[0]) == "projects" { - err = projects(token) - - printError(err) - } else if len(parts) == 2 { - err = projectsName(token, parts[1]) - - printError(err) - } else if len(parts) == 3 { - err = projectSessions(token, parts[1]) - - printError(err) - } else { - err = projectSessionId(token, parts[1], parts[3]) - - printError(err) - } - } else if len(input) >= 3 && strings.ToLower(input[:3]) == "get" { - parts := strings.Fields(input) - - err = apiGet(parts[1], token) - - printError(err) - } else if len(input) >= 8 && strings.ToLower(input[:8]) == "game-get" { - parts := strings.Fields(input) - gameToken, err := getGameUserToken(parts[1], token) - if err != nil { - fmt.Printf("\033[31mFailed: %v\033[0m\n", err) - continue - } - err = apiGet(parts[2], gameToken) - - printError(err) - } else if len(input) >= 4 && strings.ToLower(input[:4]) == "help" { - help(input) - } else if strings.ToLower(input) == "exit" { + if strings.ToLower(input) == "exit" { fmt.Println("Goodbye!") break - } else { - fmt.Printf("\033[31m%s is not a valid command!\033[0m\n", input) } + + args := strings.Fields(input) + _, err = parser.ParseArgs(args) + printError(err) } }