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