package main import ( "bufio" "bytes" "fmt" "io/ioutil" "os" "strconv" "strings" "github.com/BurntSushi/toml" ) type AppConfig struct { StorageDir string `toml:"storage_dir"` ApiToken string `toml:"api_token"` ApiSecret string `toml:"api_secret"` AppToken string `toml:"app_token"` AppSecret string `toml:"app_secret"` PullCount int `toml:"-"` ForceDownload bool `toml:"-"` Verbose bool `toml:"-"` } func NewAppConfig(args []string) (*AppConfig, error) { fmt.Println("Initializing App...") c := &AppConfig{} if err := c.ProcessArgs(args); err != nil { return nil, err } if err := c.Load(); err != nil { return nil, err } return c, c.VerifyConfig() } func (c *AppConfig) ProcessArgs(args []string) error { var err error for _, arg := range args { var k, v string if strings.ContainsRune(arg, '=') { k = arg[:strings.Index(arg, "=")] v = arg[strings.Index(arg, "=")+1:] } else { k = arg } switch k { case "-count", "-c": c.PullCount, err = strconv.Atoi(v) if err != nil { return fmt.Errorf("Invalid Count (%s): %w", v, err) } fmt.Printf("Pulling %d tweets", c.PullCount) case "-force", "-f": c.ForceDownload = true fmt.Println("Forcing Downloads") case "-help", "-h": PrintUsageAndExit() case "-verbose", "-v": c.Verbose = true } } return nil } func (c *AppConfig) Load() error { cfgPath := AppName + ".conf" tomlData, err := ioutil.ReadFile(cfgPath) if err != nil { if err = c.Save(); err != nil { return err } } if _, err := toml.Decode(string(tomlData), &c); err != nil { return err } return nil } func (c *AppConfig) Save() error { buf := new(bytes.Buffer) cfgPath := AppName + ".conf" if err := toml.NewEncoder(buf).Encode(c); err != nil { return err } return ioutil.WriteFile(cfgPath, buf.Bytes(), 0644) } func (c *AppConfig) VerifyConfig() error { configChanged := false if c.ApiToken == "" { c.ApiToken = GetDataFromUser("API Token") configChanged = true } if c.ApiSecret == "" { c.ApiSecret = GetDataFromUser("API Secret") configChanged = true } if c.AppToken == "" { c.AppToken = GetDataFromUser("App Token") configChanged = true } if c.AppSecret == "" { c.AppSecret = GetDataFromUser("App Secret") configChanged = true } exist, err := FileExists(c.StorageDir) for c.StorageDir == "" || err != nil || !exist { // Check if the storage directory exists c.StorageDir = GetDataFromUser("Image Download Directory") configChanged = true exist, err = FileExists(c.StorageDir) } if configChanged { return c.Save() } fmt.Println("Screenshot Directory:", c.StorageDir) return nil } func (c *AppConfig) GetFilePath(filename string) string { return c.StorageDir + string(os.PathSeparator) + filename } func GetDataFromUser(label string) string { reader := bufio.NewReader(os.Stdin) var res string for res == "" { fmt.Println(label + ": ") res, _ = reader.ReadString('\n') res = strings.TrimSpace(res) if res == "" { fmt.Println("Non-empty response is required") } } return res } func FileExists(path string) (bool, error) { _, err := os.Stat(path) if err == nil { return true, nil } if os.IsNotExist(err) { return false, nil } return true, err }