package main import ( "flag" "fmt" "os" "strings" "go.jolheiser.com/go-spectre" ) func main() { fs := flag.NewFlagSet("spectre", flag.ExitOnError) fs.Usage = func() { fmt.Fprintln(fs.Output(), "spectre [FLAGS] [site]") fs.PrintDefaults() } usernameFlag := fs.String("username", "", "username") secretFlag := fs.String("secret", "", "secret") counterFlag := fs.Int("counter", 1, "counter") scoperFlag := fs.String("scoper", "com.lyndir.masterpassword", "scoper base") scopeFlag := spectre.Authentication fs.Func("scope", "scope", func(s string) (err error) { scopeFlag, err = spectre.ParseScope(s) return }) var templateFlag spectre.Template fs.Func("template", "template", func(s string) (err error) { templateFlag, err = spectre.ParseTemplate(s) return }) if err := fs.Parse(os.Args[1:]); err != nil { panic(err) } if err := checkEnv(fs); err != nil { panic(err) } if templateFlag == "" { templateFlag = scopeFlag.DefaultTemplate() } if *usernameFlag == "" || *secretFlag == "" || len(os.Args) < 2 { panic("username, secret, and site are required") } s, err := spectre.New(*usernameFlag, *secretFlag, spectre.WithScoper(spectre.SimpleScoper{ Key: *scoperFlag, })) if err != nil { panic(err) } pw := s.Site(os.Args[1], spectre.WithScope(scopeFlag), spectre.WithTemplate(templateFlag), spectre.WithCounter(*counterFlag), ) fmt.Println(pw) } func checkEnv(fs *flag.FlagSet) error { provided := map[string]struct{}{} fs.Visit(func(f *flag.Flag) { provided[f.Name] = struct{}{} }) var visitErr error fs.VisitAll(func(f *flag.Flag) { if visitErr != nil { return } if _, ok := provided[f.Name]; ok { return } env := os.Getenv(fmt.Sprintf("SPECTRE_%s", strings.ToUpper(f.Name))) if env == "" { return } if err := fs.Set(f.Name, env); err != nil { visitErr = fmt.Errorf("could not set flag %q to %q", f.Name, env) } }) return nil }