Skip to content

Commit 8651d16

Browse files
authored
Merge pull request #454 from Unpackerr/unstable
Expand home dir everywhere
2 parents 781ddb2 + 4114add commit 8651d16

11 files changed

Lines changed: 135 additions & 272 deletions

File tree

pkg/unpackerr/cmdhook.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func (u *Unpackerr) validateCmdhook() error {
2323
for i := range u.Cmdhook {
2424
u.Cmdhook[i].URL = ""
2525

26+
u.Cmdhook[i].Command = expandHomedir(u.Cmdhook[i].Command)
2627
if u.Cmdhook[i].Command == "" {
2728
return ErrCmdhookNoCmd
2829
}

pkg/unpackerr/cnfgfile.go

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package unpackerr
22

33
import (
4+
"crypto/tls"
45
"fmt"
6+
"net/http"
57
"os"
68
"path/filepath"
79
"runtime"
@@ -15,6 +17,7 @@ import (
1517
homedir "github.com/mitchellh/go-homedir"
1618
"golift.io/cnfg"
1719
"golift.io/cnfgfile"
20+
"golift.io/starr"
1821
)
1922

2023
const (
@@ -31,11 +34,7 @@ func (u *Unpackerr) unmarshalConfig() (uint64, uint64, string, error) {
3134
def, cfl := configFileLocactions()
3235
// Search for one, starting with the default.
3336
for _, f = range append([]string{u.Flags.ConfigFile}, cfl...) {
34-
d, err := homedir.Expand(f)
35-
if err == nil {
36-
f = d
37-
}
38-
37+
f = expandHomedir(f)
3938
if _, err := os.Stat(f); err == nil {
4039
break // found one, bail out.
4140
} // else { u.Print("rip:", err) }
@@ -193,12 +192,8 @@ func (u *Unpackerr) createConfigFile(file string) (string, error) {
193192
return "", nil
194193
}
195194

196-
file, err := homedir.Expand(file)
195+
file, err := filepath.Abs(expandHomedir(file))
197196
if err != nil {
198-
return "", fmt.Errorf("expanding home: %w", err)
199-
}
200-
201-
if file, err = filepath.Abs(file); err != nil {
202197
return "", fmt.Errorf("absolute file: %w", err)
203198
}
204199

@@ -264,3 +259,67 @@ func isRunningInDocker() bool {
264259
_, err := os.Stat("/.dockerenv")
265260
return err == nil
266261
}
262+
263+
// expandHomedir expands a ~ to a homedir, or returns the original path in case of any error.
264+
func expandHomedir(filePath string) string {
265+
expanded, err := homedir.Expand(filePath)
266+
if err != nil {
267+
return filePath
268+
}
269+
270+
return expanded
271+
}
272+
273+
func (u *Unpackerr) validateApp(s *StarrConfig, app starr.App) error {
274+
if s.URL == "" {
275+
u.Errorf("Missing %s URL in one of your configurations, skipped and ignored.", app)
276+
return ErrInvalidURL // this error is not printed.
277+
}
278+
279+
if s.APIKey == "" {
280+
u.Errorf("Missing %s API Key in one of your configurations, skipped and ignored.", app)
281+
return ErrInvalidURL // this error is not printed.
282+
}
283+
284+
if !strings.HasPrefix(s.URL, "http://") && !strings.HasPrefix(s.URL, "https://") {
285+
return fmt.Errorf("%w: (%s) %s", ErrInvalidURL, app, s.URL)
286+
}
287+
288+
if len(s.APIKey) != apiKeyLength {
289+
return fmt.Errorf("%s (%s) %w, your key length: %d",
290+
app, s.URL, ErrInvalidKey, len(s.APIKey))
291+
}
292+
293+
if s.Timeout.Duration == 0 {
294+
s.Timeout.Duration = u.Timeout.Duration
295+
}
296+
297+
if s.DeleteDelay.Duration == 0 {
298+
s.DeleteDelay.Duration = u.DeleteDelay.Duration
299+
}
300+
301+
if s.Path != "" {
302+
s.Paths = append(s.Paths, s.Path)
303+
}
304+
305+
for idx, path := range s.Paths {
306+
s.Paths[idx] = expandHomedir(path)
307+
}
308+
309+
if len(s.Paths) == 0 {
310+
s.Paths = []string{defaultSavePath}
311+
}
312+
313+
if s.Protocols == "" {
314+
s.Protocols = defaultProtocol
315+
}
316+
317+
s.Config.Client = &http.Client{
318+
Timeout: s.Timeout.Duration,
319+
Transport: &http.Transport{
320+
TLSClientConfig: &tls.Config{InsecureSkipVerify: !s.ValidSSL}, //nolint:gosec
321+
},
322+
}
323+
324+
return nil
325+
}

pkg/unpackerr/folder.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,17 +144,27 @@ func (u *Unpackerr) PollFolders() {
144144

145145
// checkFolders stats all configured folders and returns only "good" ones.
146146
func checkFolders(folders []*FolderConfig, log Logs) ([]*FolderConfig, []string) {
147-
goodFolders := []*FolderConfig{}
148-
goodFlist := []string{}
147+
var (
148+
err error
149+
goodFolders = folders[:0]
150+
goodFlist = []string{}
151+
)
149152

150153
for _, folder := range folders {
151-
path, err := filepath.Abs(folder.Path)
154+
folder.Path, err = filepath.Abs(expandHomedir(folder.Path))
152155
if err != nil {
153156
log.Errorf("Folder '%s' (bad path): %v", folder.Path, err)
154157
continue
155158
}
156159

157-
folder.Path = path // rewrite it. might not be safe.
160+
if folder.ExtractPath != "" {
161+
folder.ExtractPath, err = filepath.Abs(expandHomedir(folder.ExtractPath))
162+
if err != nil {
163+
log.Errorf("Folder '%s' (bad extract path): %v", folder.ExtractPath, err)
164+
continue
165+
}
166+
}
167+
158168
if stat, err := os.Stat(folder.Path); err != nil {
159169
log.Errorf("Folder '%s' (cannot watch): %v", folder.Path, err)
160170
continue

pkg/unpackerr/handlers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type StarrConfig struct {
3737
Syncthing bool `json:"syncthing" toml:"syncthing" xml:"syncthing" yaml:"syncthing"`
3838
ValidSSL bool `json:"valid_ssl" toml:"valid_ssl" xml:"valid_ssl" yaml:"valid_ssl"`
3939
Timeout cnfg.Duration `json:"timeout" toml:"timeout" xml:"timeout" yaml:"timeout"`
40+
starr.Config
4041
}
4142

4243
// checkQueueChanges checks each item for state changes from the app queues.

pkg/unpackerr/lidarr.go

Lines changed: 9 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package unpackerr
22

33
import (
4-
"crypto/tls"
5-
"fmt"
6-
"net/http"
7-
"strings"
4+
"errors"
85
"sync"
96
"time"
107

@@ -14,7 +11,6 @@ import (
1411

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

27-
for i := range u.Lidarr {
28-
if u.Lidarr[i].URL == "" {
29-
u.Errorf("Missing Lidarr URL in one of your configurations, skipped and ignored.")
30-
continue
31-
}
32-
33-
if u.Lidarr[i].APIKey == "" {
34-
u.Errorf("Missing Lidarr API Key in one of your configurations, skipped and ignored.")
35-
continue
36-
}
37-
38-
if !strings.HasPrefix(u.Lidarr[i].URL, "http://") && !strings.HasPrefix(u.Lidarr[i].URL, "https://") {
39-
return fmt.Errorf("%w: (lidarr) %s", ErrInvalidURL, u.Lidarr[i].URL)
40-
}
41-
42-
if len(u.Lidarr[i].APIKey) != apiKeyLength {
43-
return fmt.Errorf("%s (%s) %w, your key length: %d",
44-
starr.Lidarr, u.Lidarr[i].URL, ErrInvalidKey, len(u.Lidarr[i].APIKey))
45-
}
46-
47-
if u.Lidarr[i].Timeout.Duration == 0 {
48-
u.Lidarr[i].Timeout.Duration = u.Timeout.Duration
49-
}
50-
51-
if u.Lidarr[i].DeleteDelay.Duration == 0 {
52-
u.Lidarr[i].DeleteDelay.Duration = u.DeleteDelay.Duration
53-
}
54-
55-
if u.Lidarr[i].Path != "" {
56-
u.Lidarr[i].Paths = append(u.Lidarr[i].Paths, u.Lidarr[i].Path)
57-
}
58-
59-
if len(u.Lidarr[i].Paths) == 0 {
60-
u.Lidarr[i].Paths = []string{defaultSavePath}
61-
}
62-
63-
if u.Lidarr[i].Protocols == "" {
64-
u.Lidarr[i].Protocols = defaultProtocol
65-
}
23+
for idx := range u.Lidarr {
24+
if err := u.validateApp(&u.Lidarr[idx].StarrConfig, starr.Lidarr); err != nil {
25+
if errors.Is(err, ErrInvalidURL) {
26+
continue // We ignore these errors, just remove the instance from the list.
27+
}
6628

67-
u.Lidarr[i].Config.Client = &http.Client{
68-
Timeout: u.Lidarr[i].Timeout.Duration,
69-
Transport: &http.Transport{
70-
TLSClientConfig: &tls.Config{InsecureSkipVerify: !u.Lidarr[i].ValidSSL}, //nolint:gosec
71-
},
29+
return err
7230
}
7331

74-
u.Lidarr[i].Lidarr = lidarr.New(&u.Lidarr[i].Config)
75-
tmp = append(tmp, u.Lidarr[i])
32+
u.Lidarr[idx].Lidarr = lidarr.New(&u.Lidarr[idx].Config)
33+
tmp = append(tmp, u.Lidarr[idx])
7634
}
7735

7836
u.Lidarr = tmp

pkg/unpackerr/logs.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ const (
2222
megabyte = 1024 * 1024
2323
logsDirMode = 0o755
2424
starrLogPfx = " => Server: "
25-
starrLogLine = "%s, apikey:%v, timeout:%v, verify ssl:%v, protos:%s, " +
26-
"syncthing: %v, delete_orig: %v, delete_delay: %v, paths:%q"
25+
starrLogLine = "%s, apikey:%v, timeout:%v, verify_ssl:%v, protos:%s, " +
26+
"syncthing:%v, delete_orig:%v, delete_delay:%v, paths:%q"
2727
)
2828

2929
// ExtractStatus is our enum for an extract's status.

pkg/unpackerr/radarr.go

Lines changed: 9 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package unpackerr
22

33
import (
4-
"crypto/tls"
5-
"fmt"
6-
"net/http"
7-
"strings"
4+
"errors"
85
"sync"
96
"time"
107

@@ -14,7 +11,6 @@ import (
1411

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

27-
for i := range u.Radarr {
28-
if u.Radarr[i].URL == "" {
29-
u.Errorf("Missing Radarr URL in one of your configurations, skipped and ignored.")
30-
continue
31-
}
32-
33-
if u.Radarr[i].APIKey == "" {
34-
u.Errorf("Missing Radarr API Key in one of your configurations, skipped and ignored.")
35-
continue
36-
}
37-
38-
if !strings.HasPrefix(u.Radarr[i].URL, "http://") && !strings.HasPrefix(u.Radarr[i].URL, "https://") {
39-
return fmt.Errorf("%w: (radarr) %s", ErrInvalidURL, u.Radarr[i].URL)
40-
}
41-
42-
if len(u.Radarr[i].APIKey) != apiKeyLength {
43-
return fmt.Errorf("%s (%s) %w, your key length: %d",
44-
starr.Radarr, u.Radarr[i].URL, ErrInvalidKey, len(u.Radarr[i].APIKey))
45-
}
46-
47-
if u.Radarr[i].Timeout.Duration == 0 {
48-
u.Radarr[i].Timeout.Duration = u.Timeout.Duration
49-
}
50-
51-
if u.Radarr[i].DeleteDelay.Duration == 0 {
52-
u.Radarr[i].DeleteDelay.Duration = u.DeleteDelay.Duration
53-
}
54-
55-
if u.Radarr[i].Path != "" {
56-
u.Radarr[i].Paths = append(u.Radarr[i].Paths, u.Radarr[i].Path)
57-
}
58-
59-
if len(u.Radarr[i].Paths) == 0 {
60-
u.Radarr[i].Paths = []string{defaultSavePath}
61-
}
62-
63-
if u.Radarr[i].Protocols == "" {
64-
u.Radarr[i].Protocols = defaultProtocol
65-
}
23+
for idx := range u.Radarr {
24+
if err := u.validateApp(&u.Radarr[idx].StarrConfig, starr.Radarr); err != nil {
25+
if errors.Is(err, ErrInvalidURL) {
26+
continue // We ignore these errors, just remove the instance from the list.
27+
}
6628

67-
u.Radarr[i].Config.Client = &http.Client{
68-
Timeout: u.Radarr[i].Timeout.Duration,
69-
Transport: &http.Transport{
70-
TLSClientConfig: &tls.Config{InsecureSkipVerify: !u.Radarr[i].ValidSSL}, //nolint:gosec
71-
},
29+
return err
7230
}
7331

74-
u.Radarr[i].Radarr = radarr.New(&u.Radarr[i].Config)
75-
tmp = append(tmp, u.Radarr[i])
32+
u.Radarr[idx].Radarr = radarr.New(&u.Radarr[idx].Config)
33+
tmp = append(tmp, u.Radarr[idx])
7634
}
7735

7836
u.Radarr = tmp

0 commit comments

Comments
 (0)