From 509622432b2e0691b7d4cf2ccf210bd639d69d63 Mon Sep 17 00:00:00 2001 From: Andinus Date: Wed, 25 Mar 2020 00:50:20 +0530 Subject: Add bpod support --- bpod/json.go | 4 +- cmd/cetus/apod.go | 7 -- cmd/cetus/bpod.go | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cmd/cetus/main.go | 12 ++-- 4 files changed, 213 insertions(+), 13 deletions(-) create mode 100644 cmd/cetus/bpod.go diff --git a/bpod/json.go b/bpod/json.go index 98b43eb..02f6fe1 100644 --- a/bpod/json.go +++ b/bpod/json.go @@ -27,9 +27,9 @@ type List struct { } // UnmarshalJson will take body as input & unmarshal it to res, -func UnmarshalJson(body string) (Res, error) { +func UnmarshalJson(body string) (BPOD, error) { list := List{} - res := Res{} + res := BPOD{} err := json.Unmarshal([]byte(body), &list) if err != nil { diff --git a/cmd/cetus/apod.go b/cmd/cetus/apod.go index 94fb36b..175d7a1 100644 --- a/cmd/cetus/apod.go +++ b/cmd/cetus/apod.go @@ -12,13 +12,6 @@ import ( "tildegit.org/andinus/cetus/notification" ) -var ( - err error - body string - file string - reqInfo map[string]string -) - func execAPOD() { apodApi := getEnv("APOD_API", "https://api.nasa.gov/planetary/apod") apodKey := getEnv("APOD_KEY", "DEMO_KEY") diff --git a/cmd/cetus/bpod.go b/cmd/cetus/bpod.go new file mode 100644 index 0000000..d26e292 --- /dev/null +++ b/cmd/cetus/bpod.go @@ -0,0 +1,203 @@ +package main + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "time" + + "tildegit.org/andinus/cetus/background" + "tildegit.org/andinus/cetus/bpod" + "tildegit.org/andinus/cetus/cache" + "tildegit.org/andinus/cetus/notification" +) + +func execBPOD() { + bpodApi := getEnv("BPOD_API", "https://www.bing.com/HPImageArchive.aspx") + + // reqInfo holds all the parameters that needs to be sent with + // the request. GetJson() will pack apiKey & date in params + // map before sending it to another function. Adding params + // here will not change the behaviour of the function, changes + // have to be made in GetJson() too. + reqInfo = make(map[string]string) + reqInfo["api"] = bpodApi + + if random { + reqInfo["random"] = "true" + } + + cacheDir := fmt.Sprintf("%s/%s", cache.GetDir(), "bpod") + os.MkdirAll(cacheDir, os.ModePerm) + + // Check if the file is available locally, if it is then don't + // download it again and get it from disk + // + // We don't know the bpod date because that will be there in + // response & we can't read the response without requesting + // it. So this will assume the bpod date to be today's date if + // *bpodRand is not set true. If *bpodRand is set true then we + // can't assume the date. Also this way too it can cause error + // if our assumed date doesn't matches date at the server. + + if !random { + // If not random and the file exists then read from + // disk, if the file doesn't exist then get it and + // save it to disk. + file = fmt.Sprintf("%s/%s.json", cacheDir, time.Now().UTC().Format("2006-01-02")) + if _, err := os.Stat(file); err == nil { + data, err := ioutil.ReadFile(file) + // Not being able to read from the cache file + // is a small error and the program shouldn't + // exit but should continue after printing the + // log so that the user can investigate it + // later. + if err != nil { + err = fmt.Errorf("%s%s\n%s", + "bpod.go: failed to read file to data: ", file, + err.Error()) + log.Println(err) + dlAndCacheBPODBody() + } + body = string(data) + + } else if os.IsNotExist(err) { + dlAndCacheBPODBody() + + } else { + // If file existed then that is handled by the + // if block, if it didn't exist then that is + // handled by the else if block. If we reach + // here then that means it's Schrödinger's + // file & something else went wrong. + log.Fatal(err) + } + } else { + // If random then get the file and save it to disk + // after unmarshal because we don't know the file name + // yet + body, err = bpod.GetJson(reqInfo) + if err != nil { + err = fmt.Errorf("%s\n%s", + "bpod.go: failed to get json response from api", + err.Error()) + log.Fatal(err) + } + + } + // Unmarshal before dump because otherwise if we come across + // the date for the first time then it would just dump and + // exit without saving it to cache. This way we first save it + // to cache if *bpodRand is true. + res, err := bpod.UnmarshalJson(body) + if err != nil { + log.Fatal(err) + } + + // Correct format + res.URL = fmt.Sprintf("%s%s", "https://www.bing.com", res.URL) + dt, err := time.Parse("20060102", res.StartDate) + if err != nil { + log.Fatal(err) + } + res.StartDate = dt.Format("2006-01-02") + + file = fmt.Sprintf("%s/%s.json", cacheDir, res.StartDate) + if random { + // Write body to the cache so that it can be read + // later. + err = ioutil.WriteFile(file, []byte(body), 0644) + + // Not being able to write to the cache file is a + // small error and the program shouldn't exit but + // should continue after printing the log so that the + // user can investigate it later. + if err != nil { + err = fmt.Errorf("%s\n%s", + "bpod.go: failed to write body to file: ", file, + err.Error()) + log.Println(err) + } + } + + if dump { + fmt.Printf(body) + } + + // Send a desktop notification if notify flag was passed. + if notify { + n := notification.Notif{} + n.Title = res.Title + n.Message = fmt.Sprintf("%s\n\n%s", + res.StartDate, + res.Copyright) + + err = n.Notify() + if err != nil { + log.Println(err) + } + } + + if print { + fmt.Printf("Title: %s\n\n", res.Title) + fmt.Printf("Copyright: %s\n", res.Copyright) + fmt.Printf("Copyright Link: %s\n", res.CopyrightLink) + fmt.Printf("Date: %s\n\n", res.StartDate) + fmt.Printf("URL: %s\n", res.URL) + } + + // Proceed only if the command was set because if it was fetch + // then it's already finished & should exit now. + if os.Args[1] == "fetch" { + os.Exit(0) + } + + // Try to set background only if the media type is an image. + // First it downloads the image to the cache directory and + // then tries to set it with feh. If the download fails then + // it exits with a non-zero exit code. + imgFile := fmt.Sprintf("%s/%s", cacheDir, res.Title) + + // Check if the file is available locally, if it is then don't + // download it again and set it from disk + if _, err := os.Stat(imgFile); os.IsNotExist(err) { + err = background.Download(imgFile, res.URL) + if err != nil { + log.Fatal(err) + } + + } else { + if err != nil { + log.Fatal(err) + } + } + + err = background.SetFromFile(imgFile) + if err != nil { + log.Fatal(err) + } +} + +func dlAndCacheBPODBody() { + body, err = bpod.GetJson(reqInfo) + if err != nil { + err = fmt.Errorf("%s\n%s", + "bpod.go: failed to get json response from api", + err.Error()) + log.Fatal(err) + } + + // Write body to the cache so that it can be read later. + err = ioutil.WriteFile(file, []byte(body), 0644) + + // Not being able to write to the cache file is a small error + // and the program shouldn't exit but should continue after + // printing the log so that the user can investigate it later. + if err != nil { + err = fmt.Errorf("%s\n%s", + "bpod.go: failed to write body to file: ", file, + err.Error()) + log.Println(err) + } +} diff --git a/cmd/cetus/main.go b/cmd/cetus/main.go index c7ffd40..1da6186 100644 --- a/cmd/cetus/main.go +++ b/cmd/cetus/main.go @@ -15,8 +15,12 @@ var ( notify bool print bool + err error + body string + file string + reqInfo map[string]string + apodDate string - // bpodApi string = getEnv("BPOD_API", "https://www.bing.com/HPImageArchive.aspx") ) func main() { @@ -85,9 +89,9 @@ func parseArgs() { cetus.Parse(os.Args[3:]) execAPOD() - // case "bpod", "bing": - // parseFlags() - // execBPOD() + case "bpod", "bing": + cetus.Parse(os.Args[3:]) + execBPOD() default: fmt.Printf("Invalid service: %q\n", os.Args[2]) printUsage() -- cgit 1.4.1-2-gfad0