Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use gopkg.in/yaml.v3 to update config.yaml #280

Merged
merged 2 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions internal/analysis/processor/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,6 @@ func New(settings *conf.Settings, ds datastore.Interface, bn *birdnet.BirdNET, m
// Load Species configs
p.Settings.Realtime.Species, _ = LoadSpeciesConfig(conf.SpeciesConfigCSV)

// Load configurations
if err := p.Settings.LoadDogBarkFilter(conf.DogBarkFilterCSV); err != nil {
log.Printf("Error loading dog bark filter: %v", err)
}

// Initialize BirdWeather client if enabled in settings
if settings.Realtime.Birdweather.Enabled {
var err error
Expand Down
109 changes: 23 additions & 86 deletions internal/conf/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ package conf

import (
"embed"
"encoding/csv"
"errors"
"fmt"
"io/fs"
"log"
"os"
"path/filepath"
"strings"
"sync"
"time"

"github.com/spf13/viper"
"gopkg.in/yaml.v3"
)

//go:embed config.yaml
Expand Down Expand Up @@ -374,14 +373,9 @@ func SaveSettings() error {
return fmt.Errorf("error finding config file: %w", err)
}

// Use UpdateYAMLConfig to write the new settings
if err := UpdateYAMLConfig(configPath, &settingsCopy); err != nil {
return fmt.Errorf("error updating config: %w", err)
}

// Save the dog bark filter species list to a CSV file
if err := settingsCopy.SaveDogBarkFilter(); err != nil {
return fmt.Errorf("error saving dog bark filter: %w", err)
// Save the settings to the config file
if err := SaveYAMLConfig(configPath, &settingsCopy); err != nil {
return fmt.Errorf("error saving config: %w", err)
}

log.Printf("Settings saved successfully to %s", configPath)
Expand All @@ -401,92 +395,35 @@ func Setting() *Settings {
return GetSettings()
}

// SaveCSVList saves a list of strings to a CSV file
func SaveCSVList(fileName string, list []string) error {
// Retrieve the default config paths
configPaths, err := GetDefaultConfigPaths()
// SaveYAMLConfig updates the YAML configuration file with new settings.
// It overwrites the existing file, not preserving comments or structure.
func SaveYAMLConfig(configPath string, settings *Settings) error {
// Marshal the settings struct to YAML
yamlData, err := yaml.Marshal(settings)
if err != nil {
return err
return fmt.Errorf("error marshaling settings to YAML: %w", err)
}

// Use the first config path to save the file
fullPath := filepath.Join(configPaths[0], fileName)

// Create the file
file, err := os.Create(fullPath)
// Write the YAML data to a temporary file
tempFile, err := os.CreateTemp(os.TempDir(), "config-*.yaml")
if err != nil {
return fmt.Errorf("error creating file: %w", err)
return fmt.Errorf("error creating temporary file: %w", err)
}
defer file.Close()
tempFileName := tempFile.Name()
defer os.Remove(tempFileName) // Clean up the temp file in case of failure

// Create a CSV writer
writer := csv.NewWriter(file)
defer writer.Flush()

// Write each item in the list as a separate row
for _, item := range list {
if err := writer.Write([]string{item}); err != nil {
return fmt.Errorf("error writing to CSV: %w", err)
}
if _, err := tempFile.Write(yamlData); err != nil {
tempFile.Close()
return fmt.Errorf("error writing to temporary file: %w", err)
}

return nil
}

// LoadDogBarkFilterConfig reads the dog bark filter configuration from a CSV file.
func (s *Settings) LoadDogBarkFilter(fileName string) error {
var Species []string

// Init the species list
s.Realtime.DogBarkFilter.Species = []string{}

// Retrieve the default config paths from your application settings.
configPaths, err := GetDefaultConfigPaths()
if err != nil {
return err
if err := tempFile.Close(); err != nil {
return fmt.Errorf("error closing temporary file: %w", err)
}

var file *os.File
// Attempt to open the file from one of the default config paths.
for _, path := range configPaths {
fullPath := filepath.Join(path, fileName)
file, err = os.Open(fullPath)
if err == nil {
break
}
}

if file == nil {
// if file is not found just return empty config and error
return fmt.Errorf("file '%s' not found in default config paths", fileName)
}
defer file.Close()

reader := csv.NewReader(file)
// Assuming no header and one species per line.
records, err := reader.ReadAll()
if err != nil {
return err
// Rename the temporary file to replace the original config file
if err := os.Rename(tempFileName, configPath); err != nil {
return fmt.Errorf("error replacing config file: %w", err)
}

// Iterate over the records and add them to the species list.
for _, record := range records {
if len(record) == 0 {
continue // Skip empty lines
}
// Assuming the species name is the only entry in each record.
species := strings.ToLower(strings.TrimSpace(record[0]))
log.Printf("Adding species '%s' to dog bark filter", species)
Species = append(Species, species)
}
log.Println("Dog bark filter config loaded")

s.Realtime.DogBarkFilter.Species = Species

return nil
}

// SaveDogBarkFilter saves the dog bark filter species list to a CSV file
func (s *Settings) SaveDogBarkFilter() error {
return SaveCSVList(DogBarkFilterCSV, s.Realtime.DogBarkFilter.Species)
}
Loading
Loading