diff options
-rw-r--r-- | README.org | 4 | ||||
-rw-r--r-- | cmd/cetus/apod.go | 108 | ||||
-rw-r--r-- | cmd/cetus/bpod.go | 135 | ||||
-rw-r--r-- | cmd/cetus/main.go | 227 | ||||
-rw-r--r-- | pkg/background/set.go | 1 |
5 files changed, 244 insertions, 231 deletions
diff --git a/README.org b/README.org index d364367..8529fe3 100644 --- a/README.org +++ b/README.org @@ -15,10 +15,6 @@ This whole project was changed multiple times, previous versions have had support for services like Unsplash Source & Wallhaven. I'm working on this because I want my desktop to have a new wallpaper everyday. -*Note*: Services were split because they didn't have much in common and it's -easier to maintain when they're split. The cetus command that bundled services -will stay as is so as to not break scripts, it will be dropped in v0.6. - Cetus v0.5 will support NASA Astronomy Picture of the Day & Bing Photo of the Day, I may add support for other services later. Both sources are very easy to work with, I personally like NASA APOD & fallback to BPOD only when it's not an diff --git a/cmd/cetus/apod.go b/cmd/cetus/apod.go new file mode 100644 index 0000000..b99d899 --- /dev/null +++ b/cmd/cetus/apod.go @@ -0,0 +1,108 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + + "framagit.org/andinus/cetus/pkg/apod" + "framagit.org/andinus/cetus/pkg/background" +) + +func execAPOD() { + // 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"] = string(*apodAPI) + reqInfo["apiKey"] = string(*apodKey) + reqInfo["date"] = string(*apodDate) + + if *apodRand { + reqInfo["date"] = apod.RandDate() + } + + cacheDir := fmt.Sprintf("%s/%s", getCacheDir(), "apod") + 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 + var body string + file := fmt.Sprintf("%s/%s", cacheDir, reqInfo["date"]) + if _, err := os.Stat(file); err == nil { + data, err := ioutil.ReadFile(file) + chkErr(err) + body = string(data) + } else if os.IsNotExist(err) { + body, err = apod.GetJson(reqInfo) + chkErr(err) + + // Write body to the cache so that it can be read + // later + err = ioutil.WriteFile(file, []byte(body), 0644) + chkErr(err) + } else { + chkErr(err) + } + + if *apodDump { + fmt.Printf(body) + os.Exit(0) + } + + res := apod.Res{} + err := apod.UnmarshalJson(&res, body) + chkErr(err) + + // res.Msg will be returned when there is error on user input + // or the api server. + if len(res.Msg) != 0 { + fmt.Printf("Message: %s", res.Msg) + os.Exit(1) + } + + // If path-only is passed then it will only print the path, + // even if quiet is passed. If the user wants the program to + // be quiet then path-only shouldn't be passed. If path-only + // is not passed & quiet is also not passed then print the + // response. + // + // Path is only printed when the media type is an image + // because res.HDURL is empty on non image media type. + if *apodPathOnly { + fmt.Println(res.HDURL) + } else if !*apodQuiet { + apod.Print(res) + } + + // 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. + if res.MediaType != "image" { + os.Exit(0) + } + imgCacheDir := fmt.Sprintf("%s/%s", cacheDir, "background") + os.MkdirAll(imgCacheDir, os.ModePerm) + imgFile := fmt.Sprintf("%s/%s", imgCacheDir, reqInfo["date"]) + + // 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.HDURL) + chkErr(err) + } else { + chkErr(err) + } + + err = background.Set(imgFile) + chkErr(err) +} diff --git a/cmd/cetus/bpod.go b/cmd/cetus/bpod.go new file mode 100644 index 0000000..f308d47 --- /dev/null +++ b/cmd/cetus/bpod.go @@ -0,0 +1,135 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + "time" + + "framagit.org/andinus/cetus/pkg/background" + "framagit.org/andinus/cetus/pkg/bpod" +) + +func execBPOD() { + // 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"] = string(*bpodAPI) + + if *bpodRand { + reqInfo["random"] = "true" + } + + cacheDir := fmt.Sprintf("%s/%s", getCacheDir(), "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. + var body string + var file string + var err error + + if !*bpodRand { + // If not *bpodRand 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", cacheDir, time.Now().UTC().Format("2006-01-02")) + if _, err := os.Stat(file); err == nil { + data, err := ioutil.ReadFile(file) + chkErr(err) + body = string(data) + } else if os.IsNotExist(err) { + body, err = bpod.GetJson(reqInfo) + chkErr(err) + + // Write body to the cache so that it can be + // read later + err = ioutil.WriteFile(file, []byte(body), 0644) + chkErr(err) + } else { + chkErr(err) + } + } else { + // If *bpodRand 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) + chkErr(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) + chkErr(err) + + // Correct format + res.Url = fmt.Sprintf("%s%s", "https://www.bing.com", res.Url) + dt, err := time.Parse("20060102", res.StartDate) + chkErr(err) + res.StartDate = dt.Format("2006-01-02") + + file = fmt.Sprintf("%s/%s", cacheDir, res.StartDate) + if *bpodRand { + // Write body to the cache so that it can be read + // later + err = ioutil.WriteFile(file, []byte(body), 0644) + chkErr(err) + } + + if *bpodDump { + fmt.Printf(body) + os.Exit(0) + } + + // If path-only is passed then it will only print the path, + // even if quiet is passed. If the user wants the program to + // be quiet then path-only shouldn't be passed. If path-only + // is not passed & quiet is also not passed then print the + // response. + // + // Path is only printed when the media type is an image + // because res.HDURL is empty on non image media type. + if *bpodPathOnly { + fmt.Println(res.Url) + } else if !*bpodQuiet { + bpod.Print(res) + } + + // 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. + imgCacheDir := fmt.Sprintf("%s/%s", cacheDir, "background") + os.MkdirAll(imgCacheDir, os.ModePerm) + imgFile := fmt.Sprintf("%s/%s", imgCacheDir, res.StartDate) + + // 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) + chkErr(err) + } else { + chkErr(err) + } + + err = background.Set(imgFile) + chkErr(err) +} diff --git a/cmd/cetus/main.go b/cmd/cetus/main.go index 2dec6fa..b039f7a 100644 --- a/cmd/cetus/main.go +++ b/cmd/cetus/main.go @@ -3,14 +3,9 @@ package main import ( "flag" "fmt" - "io/ioutil" "math/rand" "os" "time" - - "framagit.org/andinus/cetus/pkg/apod" - "framagit.org/andinus/cetus/pkg/background" - "framagit.org/andinus/cetus/pkg/bpod" ) var ( @@ -140,228 +135,6 @@ func getCacheDir() string { return cacheDir } -func execAPOD() { - // 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"] = string(*apodAPI) - reqInfo["apiKey"] = string(*apodKey) - reqInfo["date"] = string(*apodDate) - - if *apodRand { - reqInfo["date"] = apod.RandDate() - } - - cacheDir := fmt.Sprintf("%s/%s", getCacheDir(), "apod") - 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 - var body string - file := fmt.Sprintf("%s/%s", cacheDir, reqInfo["date"]) - if _, err := os.Stat(file); err == nil { - data, err := ioutil.ReadFile(file) - chkErr(err) - body = string(data) - } else if os.IsNotExist(err) { - body, err = apod.GetJson(reqInfo) - chkErr(err) - - // Write body to the cache so that it can be read - // later - err = ioutil.WriteFile(file, []byte(body), 0644) - chkErr(err) - } else { - chkErr(err) - } - - if *apodDump { - fmt.Printf(body) - os.Exit(0) - } - - res := apod.Res{} - err := apod.UnmarshalJson(&res, body) - chkErr(err) - - // res.Msg will be returned when there is error on user input - // or the api server. - if len(res.Msg) != 0 { - fmt.Printf("Message: %s", res.Msg) - os.Exit(1) - } - - // If path-only is passed then it will only print the path, - // even if quiet is passed. If the user wants the program to - // be quiet then path-only shouldn't be passed. If path-only - // is not passed & quiet is also not passed then print the - // response. - // - // Path is only printed when the media type is an image - // because res.HDURL is empty on non image media type. - if *apodPathOnly { - fmt.Println(res.HDURL) - } else if !*apodQuiet { - apod.Print(res) - } - - // 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. - if res.MediaType != "image" { - os.Exit(0) - } - imgCacheDir := fmt.Sprintf("%s/%s", cacheDir, "background") - os.MkdirAll(imgCacheDir, os.ModePerm) - imgFile := fmt.Sprintf("%s/%s", imgCacheDir, reqInfo["date"]) - - // 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.HDURL) - chkErr(err) - } else { - chkErr(err) - } - - err = background.Set(imgFile) - chkErr(err) -} - -func execBPOD() { - // 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"] = string(*bpodAPI) - - if *bpodRand { - reqInfo["random"] = "true" - } - - cacheDir := fmt.Sprintf("%s/%s", getCacheDir(), "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. - var body string - var file string - var err error - - if !*bpodRand { - // If not *bpodRand 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", cacheDir, time.Now().UTC().Format("2006-01-02")) - if _, err := os.Stat(file); err == nil { - data, err := ioutil.ReadFile(file) - chkErr(err) - body = string(data) - } else if os.IsNotExist(err) { - body, err = bpod.GetJson(reqInfo) - chkErr(err) - - // Write body to the cache so that it can be - // read later - err = ioutil.WriteFile(file, []byte(body), 0644) - chkErr(err) - } else { - chkErr(err) - } - } else { - // If *bpodRand 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) - chkErr(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) - chkErr(err) - - // Correct format - res.Url = fmt.Sprintf("%s%s", "https://www.bing.com", res.Url) - dt, err := time.Parse("20060102", res.StartDate) - chkErr(err) - res.StartDate = dt.Format("2006-01-02") - - file = fmt.Sprintf("%s/%s", cacheDir, res.StartDate) - if *bpodRand { - // Write body to the cache so that it can be read - // later - err = ioutil.WriteFile(file, []byte(body), 0644) - chkErr(err) - } - - if *bpodDump { - fmt.Printf(body) - os.Exit(0) - } - - // If path-only is passed then it will only print the path, - // even if quiet is passed. If the user wants the program to - // be quiet then path-only shouldn't be passed. If path-only - // is not passed & quiet is also not passed then print the - // response. - // - // Path is only printed when the media type is an image - // because res.HDURL is empty on non image media type. - if *bpodPathOnly { - fmt.Println(res.Url) - } else if !*bpodQuiet { - bpod.Print(res) - } - - // 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. - imgCacheDir := fmt.Sprintf("%s/%s", cacheDir, "background") - os.MkdirAll(imgCacheDir, os.ModePerm) - imgFile := fmt.Sprintf("%s/%s", imgCacheDir, res.StartDate) - - // 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) - chkErr(err) - } else { - chkErr(err) - } - - err = background.Set(imgFile) - chkErr(err) -} - func chkErr(err error) { if err != nil { fmt.Println(err) diff --git a/pkg/background/set.go b/pkg/background/set.go index 2badc48..0f7333d 100644 --- a/pkg/background/set.go +++ b/pkg/background/set.go @@ -8,6 +8,7 @@ import ( // Set calls feh to set the background func Set(path string) error { + var err error switch os.Getenv("XDG_CURRENT_DESKTOP") { case "GNOME", "Unity", "Pantheon": path = fmt.Sprintf("%s%s", "file://", path) |