From 650d578b801ec62aa1ad7c797cc95271e9fe28bb Mon Sep 17 00:00:00 2001 From: Mathis Maquenne <124215603+mathismqn@users.noreply.github.com> Date: Sun, 1 Mar 2026 21:56:54 +0100 Subject: [PATCH] refactor: remove disabled watcher feature --- cmd/watch.go | 16 ------- cmd/watch_add.go | 49 ------------------- cmd/watch_list.go | 41 ---------------- cmd/watch_remove.go | 35 -------------- cmd/watch_run.go | 30 ------------ internal/store/watched.go | 84 --------------------------------- internal/watcher/autostart.go | 38 --------------- internal/watcher/install_mac.go | 48 ------------------- internal/watcher/watcher.go | 63 ------------------------- 9 files changed, 404 deletions(-) delete mode 100644 cmd/watch.go delete mode 100644 cmd/watch_add.go delete mode 100644 cmd/watch_list.go delete mode 100644 cmd/watch_remove.go delete mode 100644 cmd/watch_run.go delete mode 100644 internal/store/watched.go delete mode 100644 internal/watcher/autostart.go delete mode 100644 internal/watcher/install_mac.go delete mode 100644 internal/watcher/watcher.go diff --git a/cmd/watch.go b/cmd/watch.go deleted file mode 100644 index 963357b..0000000 --- a/cmd/watch.go +++ /dev/null @@ -1,16 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -// NOTE: The watch command is disabled due to database concurrency issues. -// To re-enable, uncomment RootCmd.AddCommand(watchCmd) in init(). -var watchCmd = &cobra.Command{ - Use: "watch", - Short: "Watch playlists and auto-download new tracks", -} - -func init() { - // RootCmd.AddCommand(watchCmd) -} diff --git a/cmd/watch_add.go b/cmd/watch_add.go deleted file mode 100644 index 414e5f4..0000000 --- a/cmd/watch_add.go +++ /dev/null @@ -1,49 +0,0 @@ -package cmd - -import ( - "fmt" - "strings" - "time" - - "github.com/mathismqn/godeez/internal/store" - "github.com/spf13/cobra" -) - -var watchAddCmd = &cobra.Command{ - Use: "add ", - Short: "Add a playlist to the watch list", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - id := args[0] - - ok, err := store.IsWatched(id) - if err != nil { - return err - } - if ok { - fmt.Printf("Playlist %s is already being watched\n", id) - return nil - } - - playlist := &store.WatchedPlaylist{ - ID: id, - Quality: strings.ToLower(opts.Quality), - BPM: opts.BPM, - Timeout: opts.Timeout, - } - if err := playlist.Save(); err != nil { - return fmt.Errorf("failed to add playlist %s to watch list: %w", id, err) - } - - fmt.Printf("Playlist %s added to watch list\n", id) - return nil - }, -} - -func init() { - watchCmd.AddCommand(watchAddCmd) - - watchAddCmd.Flags().StringVarP(&opts.Quality, "quality", "q", "mp3_320", "download quality [mp3_128, mp3_320, flac]") - watchAddCmd.Flags().DurationVarP(&opts.Timeout, "timeout", "t", 2*time.Minute, "timeout for each download (e.g. 10s, 1m, 2m30s)") - watchAddCmd.Flags().BoolVar(&opts.BPM, "bpm", false, "fetch BPM/key and add to file tags") -} diff --git a/cmd/watch_list.go b/cmd/watch_list.go deleted file mode 100644 index 6ef1e8d..0000000 --- a/cmd/watch_list.go +++ /dev/null @@ -1,41 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "text/tabwriter" - - "github.com/mathismqn/godeez/internal/store" - "github.com/spf13/cobra" -) - -var watchListCmd = &cobra.Command{ - Use: "list", - Short: "List watched playlists", - RunE: func(cmd *cobra.Command, args []string) error { - playlists, err := store.ListWatchedPlaylists() - if err != nil { - return fmt.Errorf("failed to list watched playlists: %w", err) - } - - if len(playlists) == 0 { - fmt.Println("No watched playlists.") - return nil - } - - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) - fmt.Fprintln(w, "ID\tQuality\tFetch BPM\tTimeout") - fmt.Fprintln(w, "---\t-------\t----------\t-------") - - for _, playlist := range playlists { - fmt.Fprintf(w, "%s\t%s\t%t\t%s\n", playlist.ID, playlist.Quality, playlist.BPM, playlist.Timeout) - } - w.Flush() - - return nil - }, -} - -func init() { - watchCmd.AddCommand(watchListCmd) -} diff --git a/cmd/watch_remove.go b/cmd/watch_remove.go deleted file mode 100644 index 0c9d3b0..0000000 --- a/cmd/watch_remove.go +++ /dev/null @@ -1,35 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/mathismqn/godeez/internal/store" - "github.com/spf13/cobra" -) - -var watchRemoveCmd = &cobra.Command{ - Use: "remove ", - Short: "Remove a playlist from the watch list", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - id := args[0] - ok, err := store.IsWatched(id) - if err != nil { - return err - } - if !ok { - return fmt.Errorf("playlist %s is not being watched", id) - } - - if err := store.RemoveWatchedPlaylist(id); err != nil { - return fmt.Errorf("failed to remove playlist %s from watch list: %w", id, err) - } - fmt.Printf("Playlist %s removed from watch list\n", id) - - return nil - }, -} - -func init() { - watchCmd.AddCommand(watchRemoveCmd) -} diff --git a/cmd/watch_run.go b/cmd/watch_run.go deleted file mode 100644 index 535d9f4..0000000 --- a/cmd/watch_run.go +++ /dev/null @@ -1,30 +0,0 @@ -package cmd - -import ( - "context" - - "github.com/mathismqn/godeez/internal/config" - "github.com/mathismqn/godeez/internal/watcher" - "github.com/spf13/cobra" -) - -var watchRunCmd = &cobra.Command{ - Use: "run", - Short: "Start the background playlist watcher", - Hidden: true, - PreRun: func(cmd *cobra.Command, args []string) { - appConfig, err := config.New("") - if err != nil { - return - } - cmd.SetContext(context.WithValue(cmd.Context(), appConfigKey, appConfig)) - }, - Run: func(cmd *cobra.Command, args []string) { - appConfig, _ := cmd.Context().Value(appConfigKey).(*config.Config) - watcher.New(appConfig).Run(cmd.Context(), opts) - }, -} - -func init() { - watchCmd.AddCommand(watchRunCmd) -} diff --git a/internal/store/watched.go b/internal/store/watched.go deleted file mode 100644 index 8dd876b..0000000 --- a/internal/store/watched.go +++ /dev/null @@ -1,84 +0,0 @@ -package store - -import ( - "encoding/json" - "fmt" - "time" - - bolt "go.etcd.io/bbolt" -) - -type WatchedPlaylist struct { - ID string `json:"id"` - Quality string `json:"quality"` - BPM bool `json:"bpm"` - Timeout time.Duration `json:"timeout"` -} - -var watchedBucket = []byte("watched") - -func ListWatchedPlaylists() ([]*WatchedPlaylist, error) { - var playlists []*WatchedPlaylist - if err := db.View(func(tx *bolt.Tx) error { - b := tx.Bucket(watchedBucket) - if b == nil { - return nil - } - - return b.ForEach(func(k, v []byte) error { - var p WatchedPlaylist - if err := json.Unmarshal(v, &p); err != nil { - return err - } - playlists = append(playlists, &p) - - return nil - }) - }); err != nil { - return nil, err - } - - return playlists, nil -} - -func (p *WatchedPlaylist) Save() error { - return db.Update(func(tx *bolt.Tx) error { - b, err := tx.CreateBucketIfNotExists(watchedBucket) - if err != nil { - return err - } - - data, err := json.Marshal(p) - if err != nil { - return err - } - - return b.Put([]byte(p.ID), data) - }) -} - -func RemoveWatchedPlaylist(playlistID string) error { - return db.Update(func(tx *bolt.Tx) error { - b := tx.Bucket(watchedBucket) - if b == nil { - return fmt.Errorf("bucket not found") - } - - return b.Delete([]byte(playlistID)) - }) -} - -func IsWatched(playlistID string) (bool, error) { - var found bool - err := db.View(func(tx *bolt.Tx) error { - b := tx.Bucket(watchedBucket) - if b == nil { - return nil - } - found = b.Get([]byte(playlistID)) != nil - - return nil - }) - - return found, err -} diff --git a/internal/watcher/autostart.go b/internal/watcher/autostart.go deleted file mode 100644 index d299efa..0000000 --- a/internal/watcher/autostart.go +++ /dev/null @@ -1,38 +0,0 @@ -package watcher - -import ( - "os" - "path/filepath" - "runtime" - "strings" -) - -// EnsureAutostart installs the watcher as a system autostart service. -// Currently disabled: installAutostart is not called due to DB concurrency issues. -func EnsureAutostart(homeDir string) error { - if isAutostartInstalled(homeDir) || isTemporaryExecutable() { - return nil - } - - // return installAutostart(homeDir) - - return nil -} - -func isAutostartInstalled(homeDir string) bool { - if runtime.GOOS != "darwin" { - return false - } - - path := filepath.Join(homeDir, "Library", "LaunchAgents", "com.godeez.watch.plist") - _, err := os.Stat(path) - return err == nil -} - -func isTemporaryExecutable() bool { - exe, err := os.Executable() - if err != nil { - return true - } - return strings.Contains(exe, "go-build") -} diff --git a/internal/watcher/install_mac.go b/internal/watcher/install_mac.go deleted file mode 100644 index a159af2..0000000 --- a/internal/watcher/install_mac.go +++ /dev/null @@ -1,48 +0,0 @@ -//go:build darwin - -package watcher - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" -) - -func installAutostart(homeDir string) error { - exe, err := os.Executable() - if err != nil { - return err - } - exe, err = filepath.EvalSymlinks(exe) - if err != nil { - return err - } - - plist := fmt.Sprintf(` - - - - Label - com.godeez.watch - ProgramArguments - - %s - watch - run - - RunAtLoad - - KeepAlive - - -`, exe) - - path := filepath.Join(homeDir, "Library", "LaunchAgents", "com.godeez.watch.plist") - if err := os.WriteFile(path, []byte(plist), 0644); err != nil { - return err - } - - return exec.Command("launchctl", "load", path).Run() -} diff --git a/internal/watcher/watcher.go b/internal/watcher/watcher.go deleted file mode 100644 index fc3f9be..0000000 --- a/internal/watcher/watcher.go +++ /dev/null @@ -1,63 +0,0 @@ -package watcher - -import ( - "context" - "errors" - "log" - "os" - "path/filepath" - "time" - - "github.com/mathismqn/godeez/internal/config" - "github.com/mathismqn/godeez/internal/downloader" - "github.com/mathismqn/godeez/internal/logger" - "github.com/mathismqn/godeez/internal/store" -) - -type Watcher struct { - appConfig *config.Config - logger *logger.Logger -} - -func New(appConfig *config.Config) *Watcher { - logFile := filepath.Join(appConfig.HomeDir, ".godeez", "watcher.log") - file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) - if err != nil { - log.Fatalf("Failed to open log file: %v\n", err) - } - - l := logger.New(log.New(file, "", log.LstdFlags)) - - return &Watcher{ - appConfig: appConfig, - logger: l, - } -} - -func (w *Watcher) Run(ctx context.Context, opts downloader.Options) { - w.logger.Infof("Starting watcher...") - - for { - playlists, err := store.ListWatchedPlaylists() - if err != nil { - w.logger.Errorf("Failed to list watched playlists: %v", err) - } - - for _, playlist := range playlists { - dl := downloader.New(w.appConfig, "playlist") - dl.Logger = w.logger - if err := dl.Run(ctx, opts, playlist.ID); err != nil { - if errors.Is(err, context.Canceled) { - return - } - w.logger.Errorf("Playlist %s: %v", playlist.ID, err) - } - } - - select { - case <-ctx.Done(): - return - case <-time.After(15 * time.Minute): - } - } -}