go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/experiments/huectl/pkg/command/script.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 package command 9 10 import ( 11 "flag" 12 "fmt" 13 14 "github.com/urfave/cli/v2" 15 16 "go.charczuk.com/experiments/huectl/pkg/hue" 17 ) 18 19 // Script returns a command. 20 func Script() *cli.Command { 21 const ( 22 flagFile = "file" 23 flagRepeat = "repeat" 24 ) 25 return &cli.Command{ 26 Name: "script", 27 Usage: "Execute a script from a given json file.", 28 Flags: append( 29 DefaultFlags, 30 &cli.StringFlag{ 31 Name: flagFile, 32 Aliases: []string{"f"}, 33 Usage: "The script file path", 34 }, 35 &cli.BoolFlag{ 36 Name: flagRepeat, 37 Usage: "If the script should repeat when complete", 38 Value: true, 39 }, 40 ), 41 Action: func(c *cli.Context) error { 42 c.Context = hue.WithVerbose(c.Context, c.Bool(flagVerbose)) 43 44 scriptPath := c.String(flagFile) 45 var script []ScriptAction 46 if err := readJSON(&script, scriptPath); err != nil { 47 return fmt.Errorf("error reading script at path %s: %w", scriptPath, err) 48 } 49 50 cfg, ok, err := getConfig(c) 51 if err != nil { 52 return err 53 } 54 if ok { 55 c.Context = withConfig(c.Context, cfg) 56 } 57 58 b, err := getBridge(c) 59 if err != nil { 60 return err 61 } 62 c.Context = withBridge(c.Context, b) 63 64 if c.Bool(flagRepeat) { 65 var err error 66 for { 67 if err = runScript(c, script); err != nil { 68 return err 69 } 70 } 71 } 72 return runScript(c, script) 73 }, 74 } 75 } 76 77 func runScript(c *cli.Context, script []ScriptAction) error { 78 var cmd *cli.Command 79 var err error 80 for _, scriptStep := range script { 81 cmd = c.App.Command(scriptStep.Name) 82 err = cmd.Action(cli.NewContext(c.App, flagSetFromMap(scriptStep.Flags), c)) 83 if err != nil { 84 return err 85 } 86 } 87 return nil 88 } 89 90 func flagSetFromMap(flags map[string]string) *flag.FlagSet { 91 set := flag.NewFlagSet("", flag.ContinueOnError) 92 var arguments []string 93 for name, value := range flags { 94 set.String(name, value, "") 95 arguments = append(arguments, fmt.Sprintf("-%s=%s", name, value)) 96 } 97 _ = set.Parse(arguments) 98 return set 99 } 100 101 // ScriptContents is a list of script actions 102 type ScriptContents []ScriptAction 103 104 // ScriptAction is a specific action in a script. 105 type ScriptAction struct { 106 Name string `json:"name"` 107 Flags map[string]string `json:"flags"` 108 }