You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
3.2 KiB
151 lines
3.2 KiB
package main
|
|
|
|
import (
|
|
"context"
|
|
"git.aiterp.net/lucifer/new-server/app/client"
|
|
"git.aiterp.net/lucifer/new-server/models"
|
|
"gopkg.in/yaml.v2"
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"unicode"
|
|
)
|
|
|
|
func sceneCmd(
|
|
ctx context.Context,
|
|
c client.Client,
|
|
) {
|
|
cmd := parseCommand(os.Args[2:])
|
|
|
|
switch cmd.Name {
|
|
case "create", "update":
|
|
{
|
|
fileName := cmd.Params.Get(0).String()
|
|
if fileName == nil {
|
|
log.Fatalln("Missing filename")
|
|
}
|
|
|
|
file, err := os.Open(*fileName)
|
|
if err != nil {
|
|
log.Fatalln("Failed to open file:", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
yamlData := make(map[string]interface{})
|
|
err = yaml.NewDecoder(file).Decode(yamlData)
|
|
if err != nil {
|
|
log.Fatalln("Failed to decode file:", err)
|
|
return
|
|
}
|
|
|
|
yamlData = camelCasify(yamlData)
|
|
name, nameOk := yamlData["name"]
|
|
if !nameOk {
|
|
log.Fatalln("Missing name in yaml data.")
|
|
}
|
|
|
|
var scene models.Scene
|
|
if cmd.Name == "create" {
|
|
err := c.Fetch(ctx, "POST", "/api/scenes", &scene, yamlData)
|
|
if err != nil {
|
|
log.Fatalln("Failed to create scene:", err)
|
|
return
|
|
}
|
|
} else {
|
|
scenes, err := c.GetScenes(ctx)
|
|
if err != nil {
|
|
log.Fatalln("Failed to fetch existing scenes:", err)
|
|
return
|
|
}
|
|
|
|
id := -1
|
|
for _, scene := range scenes {
|
|
if scene.Name == name {
|
|
id = scene.ID
|
|
break
|
|
}
|
|
}
|
|
if id == -1 {
|
|
log.Fatalln("Could not find scene with name", name)
|
|
return
|
|
}
|
|
|
|
err = c.Fetch(ctx, "PUT", "/api/scenes/"+strconv.Itoa(id), &scene, yamlData)
|
|
if err != nil {
|
|
log.Fatalln("Failed to update scene:", err)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
case "assign":
|
|
{
|
|
fetch := cmd.Params.Get(0).String()
|
|
id := cmd.Params.Get(1).Int()
|
|
if fetch == nil || id == nil {
|
|
log.Println("Usage: lucy scene assign <fetch> <id> <group=S> <duration=I>")
|
|
}
|
|
|
|
devices, err := c.AssignDevice(ctx, *fetch, models.DeviceSceneAssignment{
|
|
SceneID: *id,
|
|
Group: cmd.Params.Get("group").StringOr(*fetch),
|
|
DurationMS: int64(cmd.Params.Get("duration").IntOr(0)),
|
|
})
|
|
if err != nil {
|
|
log.Println("Could not assign devices:", err)
|
|
return
|
|
}
|
|
|
|
WriteDeviceInfoTable(os.Stdout, devices)
|
|
}
|
|
}
|
|
}
|
|
|
|
func camelCasify(m map[string]interface{}) map[string]interface{} {
|
|
m2 := make(map[string]interface{}, len(m))
|
|
for key, value := range m {
|
|
b := strings.Builder{}
|
|
snake := false
|
|
for _, ch := range key {
|
|
if ch == '_' {
|
|
snake = true
|
|
} else if snake {
|
|
b.WriteRune(unicode.ToUpper(ch))
|
|
snake = false
|
|
} else {
|
|
b.WriteRune(ch)
|
|
}
|
|
}
|
|
|
|
switch value := value.(type) {
|
|
case []interface{}:
|
|
valueCopy := make([]interface{}, len(value))
|
|
for i, elem := range value {
|
|
switch elem := elem.(type) {
|
|
case map[interface{}]interface{}:
|
|
m3 := make(map[string]interface{})
|
|
for k, v := range elem {
|
|
if kStr, ok := k.(string); ok {
|
|
m3[kStr] = v
|
|
}
|
|
}
|
|
|
|
valueCopy[i] = camelCasify(m3)
|
|
case map[string]interface{}:
|
|
valueCopy[i] = camelCasify(elem)
|
|
default:
|
|
valueCopy[i] = elem
|
|
}
|
|
}
|
|
|
|
m2[b.String()] = valueCopy
|
|
case map[string]interface{}:
|
|
m2[b.String()] = camelCasify(value)
|
|
default:
|
|
m2[b.String()] = value
|
|
}
|
|
}
|
|
|
|
return m2
|
|
}
|