diff --git a/app/api/handlers.go b/app/api/handlers.go index 71cb373..29edd76 100644 --- a/app/api/handlers.go +++ b/app/api/handlers.go @@ -35,17 +35,28 @@ func EventHandlers(r gin.IRoutes) { })) r.PUT("/:id", handler(func(c *gin.Context) (interface{}, error) { - var body models.EventHandlerUpdate - err := parseBody(c, &body) - if err != nil { - return nil, err - } + handler, err := config.EventHandlerRepository().FindByID(ctxOf(c), intParam(c, "id")) if err != nil { return nil, err } - handler.ApplyUpdate(body) + + if c.Query("hard") == "true" { + var body models.EventHandler + err := parseBody(c, &body) + if err != nil || body.ID != intParam(c, "id") { + return nil, err + } + handler = &body + } else { + var body models.EventHandlerUpdate + err := parseBody(c, &body) + if err != nil { + return nil, err + } + handler.ApplyUpdate(body) + } err = config.EventHandlerRepository().Save(ctxOf(c), handler) if err != nil { diff --git a/app/client/handler.go b/app/client/handler.go index b0b4fdd..4ef960c 100644 --- a/app/client/handler.go +++ b/app/client/handler.go @@ -16,6 +16,26 @@ func (client *Client) GetHandlers(ctx context.Context) ([]models.EventHandler, e return handlers, nil } +func (client *Client) GetHandler(ctx context.Context, id int) (*models.EventHandler, error) { + var handler models.EventHandler + err := client.Fetch(ctx, "GET", fmt.Sprintf("/api/event-handlers/%d", id), &handler, nil) + if err != nil { + return nil, err + } + + return &handler, nil +} + +func (client *Client) PutHandler(ctx context.Context, handler *models.EventHandler) (*models.EventHandler, error) { + var response models.EventHandler + err := client.Fetch(ctx, "PUT", fmt.Sprintf("/api/event-handlers/%d", handler.ID), &response, handler) + if err != nil { + return nil, err + } + + return &response, nil +} + func (client *Client) AddHandler(ctx context.Context, handler models.EventHandler) (*models.EventHandler, error) { var result models.EventHandler err := client.Fetch(ctx, "POST", "/api/event-handlers", &result, handler) diff --git a/cmd/lucy/handlercmd.go b/cmd/lucy/handlercmd.go index 7d39695..9a65def 100644 --- a/cmd/lucy/handlercmd.go +++ b/cmd/lucy/handlercmd.go @@ -7,6 +7,7 @@ import ( "git.aiterp.net/lucifer/new-server/models" "log" "os" + "strings" ) func handlerCmd( @@ -38,54 +39,42 @@ func handlerCmd( log.Fatalln("Search filter needed!") } model.TargetKind, model.TargetValue = models.ParseFetchString(*fetchStr) + model = applyCmdToHandler(model, cmd) - // From / To - model.From = cmd.Params.Get("from").TimeOfDayOr(models.Never) - model.To = cmd.Params.Get("to").TimeOfDayOr(models.Never) - if model.From.IsNever() != model.To.IsNever() { - log.Fatalln("from and to must be specified together!") + newHandler, err := c.AddHandler(ctx, model) + if err != nil { + log.Fatalln(err) } - // One shot - model.OneShot = cmd.Params.Get("one-shot").StringOr("false") == "true" - - // Priority - model.Priority = cmd.Params.Get("priority").IntOr(100) - - // Conditions - model.Conditions = cmd.Params.Subset("conditions").EventConditions() - - // Power, Color, Intensity, Temperature - nds := cmd.Params.DeviceState("set-") - model.Actions.SetPower = nds.Power - model.Actions.SetColor = nds.Color - model.Actions.SetIntensity = nds.Intensity - - // Add intensity - model.Actions.AddIntensity = cmd.Params.Get("add-intensity").Float() + WriteHandlerInfoTable(os.Stdout, []models.EventHandler{*newHandler}) + case "edit": + id := cmd.Params.Get(0).IntOr(0) + if id == 0 { + log.Fatalln("ID missing") + } - // Fire - fireParams := cmd.Params.Subset("fire") - fireName := fireParams.Get("name").String() - if fireName != nil { - firePayloadParams := fireParams.Subset("payload") + model, err := c.GetHandler(ctx, id) + if err != nil { + log.Fatalln(err.Error()) + } - model.Actions.FireEvent = &models.Event{ - Name: *fireName, - Payload: make(map[string]string, len(firePayloadParams)), - } + eventStr := cmd.Params.Get("event").String() + if eventStr != nil { + model.EventName = *eventStr + } - for key, value := range firePayloadParams.StringMap() { - model.Actions.FireEvent.Payload[key] = value - } + fetchStr := cmd.Params.Get("search").String() + if fetchStr != nil { + model.TargetKind, model.TargetValue = models.ParseFetchString(*fetchStr) } - newHandler, err := c.AddHandler(ctx, model) + modified := applyCmdToHandler(*model, cmd) + returned, err := c.PutHandler(ctx, &modified) if err != nil { - log.Fatalln(err) + log.Fatalln(err.Error()) } - WriteHandlerInfoTable(os.Stdout, []models.EventHandler{*newHandler}) + WriteHandlerInfoTable(os.Stdout, []models.EventHandler{*returned}) case "delete": id := cmd.Params.Get(0).Int() if id == nil { @@ -106,3 +95,83 @@ func handlerCmd( _, _ = fmt.Fprintln(os.Stderr, helpString[1:]) } } + +func applyCmdToHandler(model models.EventHandler, cmd Command) models.EventHandler { + // Remove keys + for _, elem := range cmd.Params.Strings(1) { + if elem[0] != '-' { + continue + } + keyToRemove := elem[1:] + + if strings.HasPrefix(keyToRemove, "conditions.") { + condKeyToRemove := keyToRemove[11:] + delete(model.Conditions, condKeyToRemove) + } else if strings.HasPrefix(keyToRemove, "fire.payload.") && model.Actions.FireEvent != nil { + firePayloadKeyToRemove := keyToRemove[13:] + delete(model.Actions.FireEvent.Payload, firePayloadKeyToRemove) + } else { + switch keyToRemove { + case "set-power": + model.Actions.SetPower = nil + case "set-color": + model.Actions.SetColor = nil + case "set-intensity": + model.Actions.SetIntensity = nil + case "add-intensity": + model.Actions.AddIntensity = nil + case "fire": + fallthrough + case "fire.name": + model.Actions.FireEvent = nil + case "from": + model.From = models.Never + case "to": + model.To = models.Never + } + } + } + + // From / To + model.From = cmd.Params.Get("from").TimeOfDayOr(models.Never) + model.To = cmd.Params.Get("to").TimeOfDayOr(models.Never) + if model.From.IsNever() != model.To.IsNever() { + log.Fatalln("from and to must be specified together!") + } + + // One shot + model.OneShot = cmd.Params.Get("one-shot").StringOr("false") == "true" + + // Priority + model.Priority = cmd.Params.Get("priority").IntOr(100) + + // Conditions + model.Conditions = cmd.Params.Subset("conditions").EventConditions() + + // Power, Color, Intensity, Temperature + nds := cmd.Params.DeviceState("set-") + model.Actions.SetPower = nds.Power + model.Actions.SetColor = nds.Color + model.Actions.SetIntensity = nds.Intensity + + // Add intensity + model.Actions.AddIntensity = cmd.Params.Get("add-intensity").Float() + + // Fire + fireParams := cmd.Params.Subset("fire") + fireName := fireParams.Get("name").String() + if fireName != nil { + firePayloadParams := fireParams.Subset("payload") + + model.Actions.FireEvent = &models.Event{ + Name: *fireName, + Payload: make(map[string]string, len(firePayloadParams)), + } + + for key, value := range firePayloadParams.StringMap() { + model.Actions.FireEvent.Payload[key] = value + } + } + + return model +} diff --git a/cmd/lucy/help.go b/cmd/lucy/help.go index 3bfa856..df4da3a 100644 --- a/cmd/lucy/help.go +++ b/cmd/lucy/help.go @@ -23,6 +23,13 @@ EVENT HANDLER COMMANDS \ \ + handler edit \ + (...all arguments from 'add', appending conditions and fire payload matchers...) \ + + <-from> <-to> \ + <-set-power> <-set-color> <-set-intensity> <-set-temperature> \ + <-conditions.*> \ + <-fire> <-fire.payload.*> handler delete EVENT COMMANDS