package main import ( "encoding/json" "flag" "fmt" "io/ioutil" "log" "os" "os/exec" "path" "strconv" "strings" "time" ) type sunsetConfig struct { Files []sunsetImage `json:"files"` } type sunsetImage struct { File string `json:"file"` Time string `json:"time"` } func loadSunsetConfig(filepath string) sunsetConfig { data, err := ioutil.ReadFile(filepath) var result sunsetConfig err = json.Unmarshal(data, &result) if err != nil { log.Fatal("Failed to load file: ", err.Error()) } return result } func currentIndex(config sunsetConfig) int { currentTime := getCurrentTime() var min int = 2401 var minIndex int = -1 for i := 0; i < len(config.Files); i++ { element := getTimeSimple(config.Files[i].Time) diff := currentTime - element if diff < 0 { diff = 2400 - (diff * -1) } if diff < min { min = diff minIndex = i } } return minIndex } func nextIndex(config sunsetConfig) int { currentTime := getCurrentTime() var min int = 2401 var minIndex int = -1 for i := 0; i < len(config.Files); i++ { element := getTimeSimple(config.Files[i].Time) diff := element - currentTime if diff < 0 { diff = 2400 - (diff * -1) } if diff < min { min = diff minIndex = i } } return minIndex } func getCurrentTime() int { now := time.Now() hr := now.Hour() min := now.Minute() return hr*100 + min } func getTimeSimple(timeString string) int { hr, min := getTime(timeString) return hr*100 + min } func getNextTime(config sunsetConfig) string { index := nextIndex(config) return config.Files[index].Time } func getTime(timeString string) (int, int) { splits := strings.Split(timeString, ":") hr, _ := strconv.ParseInt(splits[0], 10, 32) min, _ := strconv.ParseInt(splits[1], 10, 32) // res, err := time.Parse("15:04", fmt.Sprintf("%02d:%02d", hr, min)) // if err != nil { // log.Fatal(err) // } return int(hr), int(min) } func getNextWait(config sunsetConfig) (int, int) { index := nextIndex(config) now := time.Now() nextHr, nextMin := getTime(config.Files[index].Time) var diffHr int var diffMin int // FIXME still not working if now.Hour() >= nextHr && now.Minute() >= nextMin { diffHr = 24 - (now.Hour() - nextHr) diffMin = 60 - (now.Minute() - nextMin) } else { diffHr = nextHr - now.Hour() diffMin = nextMin - now.Minute() } return diffHr, diffMin } func block(config sunsetConfig, command string) { for { nextHr, nextMin := getNextWait(config) timer := time.NewTimer((time.Duration(nextHr) * time.Hour) + (time.Duration(nextMin) * time.Minute)) <-timer.C log.Printf("Running command: %s\n", command) go runCommand(command) } } func runCommand(command string) { cmd := exec.Command("/usr/bin/env", "sh", "-c", command) err := cmd.Run() if err != nil { log.Printf("Command %s returned a non 0 code", command) } } func main() { printNextTime := flag.Bool("next", false, "Print the time to the next change") printNextWait := flag.Bool("wait", false, "Print the time to wait for the next change") blockFlag := flag.Bool("block", false, "Block and call the provided command when the background changes") blockCommand := flag.String("command", "", "Specify a command to run when the background changed") configFile := flag.String("file", "./sunset.json", "Specify the file to load") flag.Parse() conf := loadSunsetConfig(*configFile) if *printNextTime { fmt.Printf("%s", getNextTime(conf)) } else if *printNextWait { hr, min := getNextWait(conf) fmt.Printf("%dh%dm", hr, min) } else if *blockFlag { if *blockCommand == "" { fmt.Println("Must provide a command.") os.Exit(1) } block(conf, *blockCommand) } else { index := currentIndex(conf) absoluteImagePath := path.Join(path.Dir(*configFile), conf.Files[index].File) fmt.Printf("%s", absoluteImagePath) } }