diff options
| author | Fuwn <[email protected]> | 2026-01-19 17:57:19 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-01-19 17:57:19 -0800 |
| commit | 839611b177c4b253f6a55566dd6aaff4b8931d7f (patch) | |
| tree | 4f4ca859849d298a34844cdefe1c6ae7c85730fc | |
| parent | feat: Add configurable user_agent to bypass bot detection (diff) | |
| download | kaze-839611b177c4b253f6a55566dd6aaff4b8931d7f.tar.xz kaze-839611b177c4b253f6a55566dd6aaff4b8931d7f.zip | |
fix: Preserve config formatting when updating reset flag
Use line-based approach instead of YAML unmarshal/marshal to prevent
config file rewriting with zero values. This ensures monitors that omit
fields like interval and timeout continue to inherit from group defaults.
| -rw-r--r-- | internal/config/config.go | 75 |
1 files changed, 53 insertions, 22 deletions
diff --git a/internal/config/config.go b/internal/config/config.go index 4d428fc..5a173b6 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -3,6 +3,7 @@ package config import ( "fmt" "os" + "strings" "time" "gopkg.in/yaml.v3" @@ -350,6 +351,7 @@ type MonitorWithGroup struct { } // UpdateResetFlag updates the reset_on_next_check flag for a specific monitor in the config file +// Uses a line-based approach to preserve original formatting and omitted fields func UpdateResetFlag(configPath string, monitorName string, value bool) error { // Read the config file data, err := os.ReadFile(configPath) @@ -357,38 +359,67 @@ func UpdateResetFlag(configPath string, monitorName string, value bool) error { return fmt.Errorf("failed to read config file: %w", err) } - // Parse as YAML - var cfg Config - if err := yaml.Unmarshal(data, &cfg); err != nil { - return fmt.Errorf("failed to parse config file: %w", err) - } + lines := strings.Split(string(data), "\n") + inMonitor := false + monitorIndent := "" + foundMonitor := false + + for i := 0; i < len(lines); i++ { + line := lines[i] + trimmed := strings.TrimSpace(line) + + // Check if this is the start of our target monitor + if strings.HasPrefix(trimmed, "- name:") || strings.HasPrefix(trimmed, "name:") { + // Extract monitor name from line + namePart := strings.TrimPrefix(trimmed, "- name:") + namePart = strings.TrimPrefix(namePart, "name:") + namePart = strings.TrimSpace(namePart) + namePart = strings.Trim(namePart, "\"'") + + if namePart == monitorName { + inMonitor = true + foundMonitor = true + // Calculate the indentation level + monitorIndent = line[:len(line)-len(strings.TrimLeft(line, " \t"))] + continue + } + } - // Find and update the monitor - found := false - for i := range cfg.Groups { - for j := range cfg.Groups[i].Monitors { - if cfg.Groups[i].Monitors[j].Name == monitorName { - cfg.Groups[i].Monitors[j].ResetOnNextCheck = value - found = true + // If we're in the target monitor, look for reset_on_next_check or end of monitor + if inMonitor { + // Check if we've left the monitor section (new monitor or less indented line) + if strings.HasPrefix(trimmed, "- name:") || strings.HasPrefix(trimmed, "name:") { + // We've reached another monitor without finding reset_on_next_check + // Insert the line before this one if we're setting to false + if !value { + // Only add if setting to false (after a reset) + insertLine := monitorIndent + " reset_on_next_check: false" + lines = append(lines[:i], append([]string{insertLine}, lines[i:]...)...) + } + break + } + + // Check if this line is reset_on_next_check + if strings.Contains(trimmed, "reset_on_next_check:") { + // Update the value + if !value { + // Set to false after reset + lines[i] = monitorIndent + " reset_on_next_check: false" + } else { + // Keep as true (should already be true, but update to be sure) + lines[i] = monitorIndent + " reset_on_next_check: true" + } break } - } - if found { - break } } - if !found { + if !foundMonitor { return fmt.Errorf("monitor %q not found in config", monitorName) } - // Marshal back to YAML - newData, err := yaml.Marshal(&cfg) - if err != nil { - return fmt.Errorf("failed to marshal config: %w", err) - } - // Write back to file + newData := []byte(strings.Join(lines, "\n")) if err := os.WriteFile(configPath, newData, 0644); err != nil { return fmt.Errorf("failed to write config file: %w", err) } |