sunset/main.go
2020-10-27 22:17:37 +01:00

185 lines
3.8 KiB
Go

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)
}
}