package rclone import ( "context" "fmt" "net/url" "path/filepath" "strings" "github.com/rs/zerolog" "github.com/sirrobot01/decypharr/internal/config" ) // Mount represents a mount using the rclone RC client type Mount struct { Provider string LocalPath string WebDAVURL string logger zerolog.Logger rcManager *Manager } // NewMount creates a new RC-based mount func NewMount(provider, customRcloneMount, webdavURL string, rcManager *Manager) *Mount { cfg := config.Get() var mountPath string if customRcloneMount != "" { mountPath = customRcloneMount } else { mountPath = filepath.Join(cfg.Rclone.MountPath, provider) } _url, err := url.JoinPath(webdavURL, provider) if err != nil { _url = fmt.Sprintf("%s/%s", webdavURL, provider) } if !strings.HasSuffix(_url, "/") { _url += "/" } return &Mount{ Provider: provider, LocalPath: mountPath, WebDAVURL: _url, rcManager: rcManager, logger: rcManager.GetLogger(), } } // Mount creates the mount using rclone RC func (m *Mount) Mount(ctx context.Context) error { if m.rcManager == nil { return fmt.Errorf("rclone manager is not available") } // Check if already mounted if m.rcManager.IsMounted(m.Provider) { m.logger.Info().Msgf("Mount %s is already mounted at %s", m.Provider, m.LocalPath) return nil } m.logger.Info(). Str("provider", m.Provider). Str("webdav_url", m.WebDAVURL). Str("mount_path", m.LocalPath). Msg("Creating mount via RC") if err := m.rcManager.Mount(m.LocalPath, m.Provider, m.WebDAVURL); err != nil { m.logger.Error().Str("provider", m.Provider).Msg("Mount operation failed") return fmt.Errorf("mount failed for %s", m.Provider) } m.logger.Info().Msgf("Successfully mounted %s WebDAV at %s via RC", m.Provider, m.LocalPath) return nil } // Unmount removes the mount using rclone RC func (m *Mount) Unmount() error { if m.rcManager == nil { m.logger.Warn().Msg("Rclone manager is not available, skipping unmount") return nil } if !m.rcManager.IsMounted(m.Provider) { m.logger.Info().Msgf("Mount %s is not mounted, skipping unmount", m.Provider) return nil } m.logger.Info().Str("provider", m.Provider).Msg("Unmounting via RC") if err := m.rcManager.Unmount(m.Provider); err != nil { return fmt.Errorf("failed to unmount %s via RC: %w", m.Provider, err) } m.logger.Info().Msgf("Successfully unmounted %s", m.Provider) return nil } // IsMounted checks if the mount is active via RC func (m *Mount) IsMounted() bool { if m.rcManager == nil { return false } return m.rcManager.IsMounted(m.Provider) } // RefreshDir refreshes directories in the mount func (m *Mount) RefreshDir(dirs []string) error { if m.rcManager == nil { return fmt.Errorf("rclone manager is not available") } if !m.IsMounted() { return fmt.Errorf("provider %s not properly mounted. Skipping refreshes", m.Provider) } if err := m.rcManager.RefreshDir(m.Provider, dirs); err != nil { return fmt.Errorf("failed to refresh directories for %s: %w", m.Provider, err) } return nil } // GetMountInfo returns mount information func (m *Mount) GetMountInfo() (*MountInfo, bool) { if m.rcManager == nil { return nil, false } return m.rcManager.GetMountInfo(m.Provider) }