From 7cd8becb29c96a06f0c1b0cfb623ed5e98911613 Mon Sep 17 00:00:00 2001
From: Ethel Morgan <eth@ethulhu.co.uk>
Date: Tue, 7 Jul 2020 18:37:42 +0100
Subject: initial hack sesh

---
 config/config.go | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)
 create mode 100644 config/config.go

(limited to 'config')

diff --git a/config/config.go b/config/config.go
new file mode 100644
index 0000000..38bf73c
--- /dev/null
+++ b/config/config.go
@@ -0,0 +1,141 @@
+// SPDX-FileCopyrightText: 2020 Ethel Morgan
+//
+// SPDX-License-Identifier: MIT
+
+package config
+
+import (
+	"encoding/json"
+	"errors"
+	"io/ioutil"
+	"net/url"
+)
+
+type (
+	Action struct {
+		Name     string
+		Triggers []Trigger
+		Outputs  []Output
+	}
+
+	Trigger struct {
+		URL        *url.URL
+		FormValues url.Values
+	}
+
+	OutputKind int
+	Output     struct {
+		Kind OutputKind
+		Name string
+
+		URL        *url.URL
+		FormValues url.Values
+
+		MQTT  *url.URL
+		Value string
+	}
+
+	Config struct {
+		Actions map[string]Action
+	}
+
+	config struct {
+		Actions map[string]struct {
+			Triggers []struct {
+				URL        uurl              `json:"url"`
+				FormValues map[string]string `json:"formValues"`
+			} `json:"triggers"`
+			Outputs []struct {
+				URL        uurl              `json:"url"`
+				FormValues map[string]string `json:"formValues"`
+				MQTT       uurl              `json:"mqtt"`
+				Value      string            `json:"value"`
+			} `json:"outputs"`
+		} `json:"actions"`
+	}
+
+	uurl struct {
+		*url.URL
+	}
+)
+
+const (
+	HTTPOutput OutputKind = iota
+	MQTTOutput
+)
+
+func ParseFile(path string) (*Config, error) {
+	bytes, err := ioutil.ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+
+	raw := config{}
+	if err := json.Unmarshal(bytes, &raw); err != nil {
+		return nil, err
+	}
+
+	return configFromConfig(raw)
+}
+
+func configFromConfig(raw config) (*Config, error) {
+	c := &Config{
+		Actions: map[string]Action{},
+	}
+
+	for k, v := range raw.Actions {
+		action := Action{
+			Name: k,
+		}
+
+		for _, rawTrigger := range v.Triggers {
+			trigger := Trigger{
+				URL:        rawTrigger.URL.URL,
+				FormValues: urlValuesFromRawValues(rawTrigger.FormValues),
+			}
+			action.Triggers = append(action.Triggers, trigger)
+		}
+		for _, rawOutput := range v.Outputs {
+			output := Output{
+				URL:        rawOutput.URL.URL,
+				FormValues: urlValuesFromRawValues(rawOutput.FormValues),
+				MQTT:       rawOutput.MQTT.URL,
+				Value:      rawOutput.Value,
+			}
+			switch {
+			case output.URL != nil && output.MQTT == nil:
+				output.Kind = HTTPOutput
+			case output.URL == nil && output.MQTT != nil:
+				output.Kind = MQTTOutput
+			default:
+				return nil, errors.New("outputs must be URL xor MQTT")
+			}
+			action.Outputs = append(action.Outputs, output)
+		}
+
+		c.Actions[k] = action
+
+	}
+
+	return c, nil
+}
+
+func (u uurl) MarshalText() ([]byte, error) {
+	return []byte(u.String()), nil
+}
+func (u *uurl) UnmarshalText(raw []byte) error {
+	uu, err := url.Parse(string(raw))
+	if err != nil {
+		return err
+	}
+	u.URL = uu
+	return nil
+}
+
+func urlValuesFromRawValues(raw map[string]string) url.Values {
+	urlValues := map[string][]string{}
+	for k, v := range raw {
+		urlValues[k] = []string{v}
+	}
+	return urlValues
+}
-- 
cgit v1.2.3