Skip to content
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
1 change: 1 addition & 0 deletions pkg/unpackerr/cmdhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func (u *Unpackerr) validateCmdhook() error {
for i := range u.Cmdhook {
u.Cmdhook[i].URL = ""

u.Cmdhook[i].Command = expandHomedir(u.Cmdhook[i].Command)
if u.Cmdhook[i].Command == "" {
return ErrCmdhookNoCmd
}
Expand Down
79 changes: 69 additions & 10 deletions pkg/unpackerr/cnfgfile.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package unpackerr

import (
"crypto/tls"
"fmt"
"net/http"
"os"
"path/filepath"
"runtime"
Expand All @@ -15,6 +17,7 @@ import (
homedir "github.com/mitchellh/go-homedir"
"golift.io/cnfg"
"golift.io/cnfgfile"
"golift.io/starr"
)

const (
Expand All @@ -31,11 +34,7 @@ func (u *Unpackerr) unmarshalConfig() (uint64, uint64, string, error) {
def, cfl := configFileLocactions()
// Search for one, starting with the default.
for _, f = range append([]string{u.Flags.ConfigFile}, cfl...) {
d, err := homedir.Expand(f)
if err == nil {
f = d
}

f = expandHomedir(f)
if _, err := os.Stat(f); err == nil {
break // found one, bail out.
} // else { u.Print("rip:", err) }
Expand Down Expand Up @@ -193,12 +192,8 @@ func (u *Unpackerr) createConfigFile(file string) (string, error) {
return "", nil
}

file, err := homedir.Expand(file)
file, err := filepath.Abs(expandHomedir(file))
if err != nil {
return "", fmt.Errorf("expanding home: %w", err)
}

if file, err = filepath.Abs(file); err != nil {
return "", fmt.Errorf("absolute file: %w", err)
}

Expand Down Expand Up @@ -264,3 +259,67 @@ func isRunningInDocker() bool {
_, err := os.Stat("/.dockerenv")
return err == nil
}

// expandHomedir expands a ~ to a homedir, or returns the original path in case of any error.
func expandHomedir(filePath string) string {
expanded, err := homedir.Expand(filePath)
if err != nil {
return filePath
}

return expanded
}

func (u *Unpackerr) validateApp(s *StarrConfig, app starr.App) error {
if s.URL == "" {
u.Errorf("Missing %s URL in one of your configurations, skipped and ignored.", app)
return ErrInvalidURL // this error is not printed.
}

if s.APIKey == "" {
u.Errorf("Missing %s API Key in one of your configurations, skipped and ignored.", app)
return ErrInvalidURL // this error is not printed.
}

if !strings.HasPrefix(s.URL, "http://") && !strings.HasPrefix(s.URL, "https://") {
return fmt.Errorf("%w: (%s) %s", ErrInvalidURL, app, s.URL)
}

if len(s.APIKey) != apiKeyLength {
return fmt.Errorf("%s (%s) %w, your key length: %d",
app, s.URL, ErrInvalidKey, len(s.APIKey))
}

if s.Timeout.Duration == 0 {
s.Timeout.Duration = u.Timeout.Duration
}

if s.DeleteDelay.Duration == 0 {
s.DeleteDelay.Duration = u.DeleteDelay.Duration
}

if s.Path != "" {
s.Paths = append(s.Paths, s.Path)
}

for idx, path := range s.Paths {
s.Paths[idx] = expandHomedir(path)
}

if len(s.Paths) == 0 {
s.Paths = []string{defaultSavePath}
}

if s.Protocols == "" {
s.Protocols = defaultProtocol
}

s.Config.Client = &http.Client{
Timeout: s.Timeout.Duration,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: !s.ValidSSL}, //nolint:gosec
},
}

return nil
}
18 changes: 14 additions & 4 deletions pkg/unpackerr/folder.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,27 @@ func (u *Unpackerr) PollFolders() {

// checkFolders stats all configured folders and returns only "good" ones.
func checkFolders(folders []*FolderConfig, log Logs) ([]*FolderConfig, []string) {
goodFolders := []*FolderConfig{}
goodFlist := []string{}
var (
err error
goodFolders = folders[:0]
goodFlist = []string{}
)

for _, folder := range folders {
path, err := filepath.Abs(folder.Path)
folder.Path, err = filepath.Abs(expandHomedir(folder.Path))
if err != nil {
log.Errorf("Folder '%s' (bad path): %v", folder.Path, err)
continue
}

folder.Path = path // rewrite it. might not be safe.
if folder.ExtractPath != "" {
folder.ExtractPath, err = filepath.Abs(expandHomedir(folder.ExtractPath))
if err != nil {
log.Errorf("Folder '%s' (bad extract path): %v", folder.ExtractPath, err)
continue
}
}

if stat, err := os.Stat(folder.Path); err != nil {
log.Errorf("Folder '%s' (cannot watch): %v", folder.Path, err)
continue
Expand Down
1 change: 1 addition & 0 deletions pkg/unpackerr/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type StarrConfig struct {
Syncthing bool `json:"syncthing" toml:"syncthing" xml:"syncthing" yaml:"syncthing"`
ValidSSL bool `json:"valid_ssl" toml:"valid_ssl" xml:"valid_ssl" yaml:"valid_ssl"`
Timeout cnfg.Duration `json:"timeout" toml:"timeout" xml:"timeout" yaml:"timeout"`
starr.Config
}

// checkQueueChanges checks each item for state changes from the app queues.
Expand Down
60 changes: 9 additions & 51 deletions pkg/unpackerr/lidarr.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package unpackerr

import (
"crypto/tls"
"fmt"
"net/http"
"strings"
"errors"
"sync"
"time"

Expand All @@ -14,7 +11,6 @@ import (

// LidarrConfig represents the input data for a Lidarr server.
type LidarrConfig struct {
starr.Config
StarrConfig
Queue *lidarr.Queue `json:"-" toml:"-" xml:"-" yaml:"-"`
*lidarr.Lidarr `json:"-" toml:"-" xml:"-" yaml:"-"`
Expand All @@ -24,55 +20,17 @@ type LidarrConfig struct {
func (u *Unpackerr) validateLidarr() error {
tmp := u.Lidarr[:0]

for i := range u.Lidarr {
if u.Lidarr[i].URL == "" {
u.Errorf("Missing Lidarr URL in one of your configurations, skipped and ignored.")
continue
}

if u.Lidarr[i].APIKey == "" {
u.Errorf("Missing Lidarr API Key in one of your configurations, skipped and ignored.")
continue
}

if !strings.HasPrefix(u.Lidarr[i].URL, "http://") && !strings.HasPrefix(u.Lidarr[i].URL, "https://") {
return fmt.Errorf("%w: (lidarr) %s", ErrInvalidURL, u.Lidarr[i].URL)
}

if len(u.Lidarr[i].APIKey) != apiKeyLength {
return fmt.Errorf("%s (%s) %w, your key length: %d",
starr.Lidarr, u.Lidarr[i].URL, ErrInvalidKey, len(u.Lidarr[i].APIKey))
}

if u.Lidarr[i].Timeout.Duration == 0 {
u.Lidarr[i].Timeout.Duration = u.Timeout.Duration
}

if u.Lidarr[i].DeleteDelay.Duration == 0 {
u.Lidarr[i].DeleteDelay.Duration = u.DeleteDelay.Duration
}

if u.Lidarr[i].Path != "" {
u.Lidarr[i].Paths = append(u.Lidarr[i].Paths, u.Lidarr[i].Path)
}

if len(u.Lidarr[i].Paths) == 0 {
u.Lidarr[i].Paths = []string{defaultSavePath}
}

if u.Lidarr[i].Protocols == "" {
u.Lidarr[i].Protocols = defaultProtocol
}
for idx := range u.Lidarr {
if err := u.validateApp(&u.Lidarr[idx].StarrConfig, starr.Lidarr); err != nil {
if errors.Is(err, ErrInvalidURL) {
continue // We ignore these errors, just remove the instance from the list.
}

u.Lidarr[i].Config.Client = &http.Client{
Timeout: u.Lidarr[i].Timeout.Duration,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: !u.Lidarr[i].ValidSSL}, //nolint:gosec
},
return err
}

u.Lidarr[i].Lidarr = lidarr.New(&u.Lidarr[i].Config)
tmp = append(tmp, u.Lidarr[i])
u.Lidarr[idx].Lidarr = lidarr.New(&u.Lidarr[idx].Config)
tmp = append(tmp, u.Lidarr[idx])
}

u.Lidarr = tmp
Expand Down
4 changes: 2 additions & 2 deletions pkg/unpackerr/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const (
megabyte = 1024 * 1024
logsDirMode = 0o755
starrLogPfx = " => Server: "
starrLogLine = "%s, apikey:%v, timeout:%v, verify ssl:%v, protos:%s, " +
"syncthing: %v, delete_orig: %v, delete_delay: %v, paths:%q"
starrLogLine = "%s, apikey:%v, timeout:%v, verify_ssl:%v, protos:%s, " +
"syncthing:%v, delete_orig:%v, delete_delay:%v, paths:%q"
)

// ExtractStatus is our enum for an extract's status.
Expand Down
60 changes: 9 additions & 51 deletions pkg/unpackerr/radarr.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package unpackerr

import (
"crypto/tls"
"fmt"
"net/http"
"strings"
"errors"
"sync"
"time"

Expand All @@ -14,7 +11,6 @@ import (

// RadarrConfig represents the input data for a Radarr server.
type RadarrConfig struct {
starr.Config
StarrConfig
Queue *radarr.Queue `json:"-" toml:"-" xml:"-" yaml:"-"`
sync.RWMutex `json:"-" toml:"-" xml:"-" yaml:"-"`
Expand All @@ -24,55 +20,17 @@ type RadarrConfig struct {
func (u *Unpackerr) validateRadarr() error {
tmp := u.Radarr[:0]

for i := range u.Radarr {
if u.Radarr[i].URL == "" {
u.Errorf("Missing Radarr URL in one of your configurations, skipped and ignored.")
continue
}

if u.Radarr[i].APIKey == "" {
u.Errorf("Missing Radarr API Key in one of your configurations, skipped and ignored.")
continue
}

if !strings.HasPrefix(u.Radarr[i].URL, "http://") && !strings.HasPrefix(u.Radarr[i].URL, "https://") {
return fmt.Errorf("%w: (radarr) %s", ErrInvalidURL, u.Radarr[i].URL)
}

if len(u.Radarr[i].APIKey) != apiKeyLength {
return fmt.Errorf("%s (%s) %w, your key length: %d",
starr.Radarr, u.Radarr[i].URL, ErrInvalidKey, len(u.Radarr[i].APIKey))
}

if u.Radarr[i].Timeout.Duration == 0 {
u.Radarr[i].Timeout.Duration = u.Timeout.Duration
}

if u.Radarr[i].DeleteDelay.Duration == 0 {
u.Radarr[i].DeleteDelay.Duration = u.DeleteDelay.Duration
}

if u.Radarr[i].Path != "" {
u.Radarr[i].Paths = append(u.Radarr[i].Paths, u.Radarr[i].Path)
}

if len(u.Radarr[i].Paths) == 0 {
u.Radarr[i].Paths = []string{defaultSavePath}
}

if u.Radarr[i].Protocols == "" {
u.Radarr[i].Protocols = defaultProtocol
}
for idx := range u.Radarr {
if err := u.validateApp(&u.Radarr[idx].StarrConfig, starr.Radarr); err != nil {
if errors.Is(err, ErrInvalidURL) {
continue // We ignore these errors, just remove the instance from the list.
}

u.Radarr[i].Config.Client = &http.Client{
Timeout: u.Radarr[i].Timeout.Duration,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: !u.Radarr[i].ValidSSL}, //nolint:gosec
},
return err
}

u.Radarr[i].Radarr = radarr.New(&u.Radarr[i].Config)
tmp = append(tmp, u.Radarr[i])
u.Radarr[idx].Radarr = radarr.New(&u.Radarr[idx].Config)
tmp = append(tmp, u.Radarr[idx])
}

u.Radarr = tmp
Expand Down
Loading