package main import ( "encoding/json" "io/ioutil" "log" "net/http" "github.com/spf13/viper" "gopkg.in/yaml.v2" ) type webhook struct { Name string Path string NumSwitches int `yaml:"num_switches"` MomentarySwitches []int `yaml:"momentary_switches"` SwitchStates []int `json:switch_states` } func debug(msg string, args ...interface{}) { if viper.GetBool("Debug") { log.Printf(msg, args...) } } func initWebhooks(filename string) { bytes, err := ioutil.ReadFile(filename) if err != nil { log.Panicf("Couldn't read config file: %s", err) } var hooks []webhook err = yaml.Unmarshal(bytes, &hooks) if err != nil { log.Panicf("Couldn't parse webhook file: %v", err) } debug("Webhook definitions:") debug("%v", hooks) for _, v := range hooks { v.SwitchStates = make([]int, v.NumSwitches) http.HandleFunc("/"+v.Path, makeWebhookHandler(v)) } } func runServer() { log.Printf("Starting server on port %s", viper.GetString("ListenPort")) log.Fatal(http.ListenAndServe(":"+viper.GetString("ListenPort"), nil)) } func makeWebhookHandler(hook webhook) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { webhookRead(hook, w, r) } else if r.Method == "POST" { webhookWrite(hook, w, r) } } } func webhookRead(hook webhook, w http.ResponseWriter, r *http.Request) { err := json.NewEncoder(w).Encode(hook.SwitchStates) if err != nil { log.Printf("Failed to send response: %v", err) return } // momentary switches have been read, so make sure they're 0 // next time for _, i := range hook.MomentarySwitches { hook.SwitchStates[i] = 0 } } func webhookWrite(hook webhook, w http.ResponseWriter, r *http.Request) { err := json.NewDecoder(r.Body).Decode(&hook.SwitchStates) if err != nil { log.Printf("Failed to parse json for '%s': %v", hook.Name, err) http.Error(w, "Failed to parse json", http.StatusBadRequest) return } } func main() { // read environment config viper.BindEnv("Debug", "DEBUG") viper.BindEnv("WebhookFile", "WEBHOOK_CONFIG_FILE") viper.BindEnv("ListenPort", "PORT") viper.SetDefault("ListenPort", "7200") viper.SetDefault("WebhookFile", "./webhooks.yaml") viper.SetDefault("Debug", false) // read webhook config initWebhooks(viper.GetString("WebhookFile")) // serve app runServer() }