Skip to content

Commit 705de2d

Browse files
committed
Merge branch 'beta'
2 parents 87bf8d0 + 54c421a commit 705de2d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+6333
-3117
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: Bug Report
2+
description: 'Report a new bug'
3+
labels: ['Type: Bug', 'Status: Needs Triage']
4+
body:
5+
- type: checkboxes
6+
attributes:
7+
label: Is there an existing issue for this?
8+
description: Please search to see if an open or closed issue already exists for the bug you encountered. If a bug exists and is closed note that it may only be fixed in an unstable branch.
9+
options:
10+
- label: I have searched the existing open and closed issues
11+
required: true
12+
- type: textarea
13+
attributes:
14+
label: Current Behavior
15+
description: A concise description of what you're experiencing.
16+
validations:
17+
required: true
18+
- type: textarea
19+
attributes:
20+
label: Expected Behavior
21+
description: A concise description of what you expected to happen.
22+
validations:
23+
required: true
24+
- type: textarea
25+
attributes:
26+
label: Steps To Reproduce
27+
description: Steps to reproduce the behavior.
28+
placeholder: |
29+
1. In this environment...
30+
2. With this config...
31+
3. Run '...'
32+
4. See error...
33+
validations:
34+
required: false
35+
- type: textarea
36+
attributes:
37+
label: Environment
38+
description: |
39+
examples:
40+
- **OS**: Ubuntu 20.04
41+
- **Version**: v1.0.0
42+
- **Docker Install**: Yes
43+
- **Browser**: Firefox 90 (If UI related)
44+
value: |
45+
- OS:
46+
- Version:
47+
- Docker Install:
48+
- Browser:
49+
render: markdown
50+
validations:
51+
required: true
52+
- type: dropdown
53+
attributes:
54+
label: What branch are you running?
55+
options:
56+
- Main/Latest
57+
- Beta
58+
- Experimental
59+
validations:
60+
required: true
61+
- type: textarea
62+
attributes:
63+
label: Trace Logs? **Not Optional**
64+
description: |
65+
Trace Logs
66+
- are **required** for bug reports
67+
- are not optional
68+
validations:
69+
required: true
70+
- type: checkboxes
71+
attributes:
72+
label: Trace Logs have been provided as applicable
73+
description: Trace logs are **generally required** and are not optional for all bug reports and contain `trace`. Info logs are invalid for bug reports and do not contain `debug` nor `trace`
74+
options:
75+
- label: I have read and followed the steps in the wiki link above and provided the required trace logs - the logs contain `trace` - that are relevant and show this issue.
76+
required: true
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Feature Request
2+
description: 'Suggest an idea for Decypharr'
3+
labels: ['Type: Feature Request', 'Status: Needs Triage']
4+
body:
5+
- type: checkboxes
6+
attributes:
7+
label: Is there an existing issue for this?
8+
description: Please search to see if an open or closed issue already exists for the feature you are requesting. If a request exists and is closed note that it may only be fixed in an unstable branch.
9+
options:
10+
- label: I have searched the existing open and closed issues
11+
required: true
12+
- type: textarea
13+
attributes:
14+
label: Is your feature request related to a problem? Please describe
15+
description: A clear and concise description of what the problem is.
16+
validations:
17+
required: true
18+
- type: textarea
19+
attributes:
20+
label: Describe the solution you'd like
21+
description: A clear and concise description of what you want to happen.
22+
validations:
23+
required: true
24+
- type: textarea
25+
attributes:
26+
label: Describe alternatives you've considered
27+
description: A clear and concise description of any alternative solutions or features you've considered.
28+
validations:
29+
required: true
30+
- type: textarea
31+
attributes:
32+
label: Anything else?
33+
description: |
34+
Links? References? Mockups? Anything that will give us more context about the feature you are encountering!
35+
36+
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
37+
validations:
38+
required: true

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ EXPOSE 8282
6161
VOLUME ["/app"]
6262
USER nonroot:nonroot
6363

64-
HEALTHCHECK --interval=3s --retries=10 CMD ["/usr/bin/healthcheck", "--config", "/app"]
64+
65+
# Base healthcheck
66+
HEALTHCHECK --interval=3s --retries=10 CMD ["/usr/bin/healthcheck", "--config", "/app", "--basic"]
6567

6668
CMD ["/usr/bin/decypharr", "--config", "/app"]

README.md

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66

77
## What is Decypharr?
88

9-
Decypharr combines the power of QBittorrent with popular Debrid services to enhance your media management. It provides a familiar interface for Sonarr, Radarr, and other \*Arr applications while leveraging the capabilities of Debrid providers.
9+
Decypharr combines the power of QBittorrent with popular Debrid services to enhance your media management. It provides a familiar interface for Sonarr, Radarr, and other \*Arr applications.
1010

1111
## Features
1212

13-
- 🔄 Mock Qbittorent API that supports the Arrs (Sonarr, Radarr, Lidarr etc)
14-
- 🖥️ Full-fledged UI for managing torrents
15-
- 🛡️ Proxy support for filtering out un-cached Debrid torrents
16-
- 🔌 Multiple Debrid providers support
17-
- 📁 WebDAV server support for each debrid provider
18-
- 🔧 Repair Worker for missing files
13+
- Mock Qbittorent API that supports the Arrs (Sonarr, Radarr, Lidarr etc)
14+
- Full-fledged UI for managing torrents
15+
- Proxy support for filtering out un-cached Debrid torrents
16+
- Multiple Debrid providers support
17+
- WebDAV server support for each debrid provider
18+
- Repair Worker for missing files
1919

2020
## Supported Debrid Providers
2121

@@ -36,14 +36,9 @@ services:
3636
container_name: decypharr
3737
ports:
3838
- "8282:8282" # qBittorrent
39-
user: "1000:1000"
4039
volumes:
4140
- /mnt/:/mnt
4241
- ./configs/:/app # config.json must be in this directory
43-
environment:
44-
- PUID=1000
45-
- PGID=1000
46-
- UMASK=002
4742
restart: unless-stopped
4843
```
4944

cmd/decypharr/main.go

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ import (
77
"github.com/sirrobot01/decypharr/internal/logger"
88
"github.com/sirrobot01/decypharr/pkg/qbit"
99
"github.com/sirrobot01/decypharr/pkg/server"
10-
"github.com/sirrobot01/decypharr/pkg/service"
10+
"github.com/sirrobot01/decypharr/pkg/store"
1111
"github.com/sirrobot01/decypharr/pkg/version"
1212
"github.com/sirrobot01/decypharr/pkg/web"
1313
"github.com/sirrobot01/decypharr/pkg/webdav"
14-
"github.com/sirrobot01/decypharr/pkg/worker"
1514
"net/http"
1615
"os"
1716
"runtime"
@@ -62,7 +61,7 @@ func Start(ctx context.Context) error {
6261
qb := qbit.New()
6362
wd := webdav.New()
6463

65-
ui := web.New(qb).Routes()
64+
ui := web.New().Routes()
6665
webdavRoutes := wd.Routes()
6766
qbitRoutes := qb.Routes()
6867

@@ -76,7 +75,7 @@ func Start(ctx context.Context) error {
7675

7776
done := make(chan struct{})
7877
go func(ctx context.Context) {
79-
if err := startServices(ctx, wd, srv); err != nil {
78+
if err := startServices(ctx, cancelSvc, wd, srv); err != nil {
8079
_log.Error().Err(err).Msg("Error starting services")
8180
cancelSvc()
8281
}
@@ -95,20 +94,20 @@ func Start(ctx context.Context) error {
9594
_log.Info().Msg("Restarting Decypharr...")
9695
<-done // wait for them to finish
9796
qb.Reset()
98-
service.Reset()
97+
store.Reset()
9998

10099
// rebuild svcCtx off the original parent
101100
svcCtx, cancelSvc = context.WithCancel(ctx)
102101
runtime.GC()
103102

104103
config.Reload()
105-
service.Reset()
104+
store.Reset()
106105
// loop will restart services automatically
107106
}
108107
}
109108
}
110109

111-
func startServices(ctx context.Context, wd *webdav.WebDav, srv *server.Server) error {
110+
func startServices(ctx context.Context, cancelSvc context.CancelFunc, wd *webdav.WebDav, srv *server.Server) error {
112111
var wg sync.WaitGroup
113112
errChan := make(chan error)
114113

@@ -146,11 +145,7 @@ func startServices(ctx context.Context, wd *webdav.WebDav, srv *server.Server) e
146145
})
147146

148147
safeGo(func() error {
149-
return worker.Start(ctx)
150-
})
151-
152-
safeGo(func() error {
153-
arr := service.GetService().Arr
148+
arr := store.Get().Arr()
154149
if arr == nil {
155150
return nil
156151
}
@@ -159,16 +154,20 @@ func startServices(ctx context.Context, wd *webdav.WebDav, srv *server.Server) e
159154

160155
if cfg := config.Get(); cfg.Repair.Enabled {
161156
safeGo(func() error {
162-
r := service.GetService().Repair
163-
if r != nil {
164-
if err := r.Start(ctx); err != nil {
157+
repair := store.Get().Repair()
158+
if repair != nil {
159+
if err := repair.Start(ctx); err != nil {
165160
_log.Error().Err(err).Msg("repair failed")
166161
}
167162
}
168163
return nil
169164
})
170165
}
171166

167+
safeGo(func() error {
168+
return store.Get().StartQueueSchedule(ctx)
169+
})
170+
172171
go func() {
173172
wg.Wait()
174173
close(errChan)
@@ -178,7 +177,11 @@ func startServices(ctx context.Context, wd *webdav.WebDav, srv *server.Server) e
178177
for err := range errChan {
179178
if err != nil {
180179
_log.Error().Err(err).Msg("Service error detected")
181-
// Don't shut down the whole app
180+
// If the error is critical, return it to stop the main loop
181+
if ctx.Err() == nil {
182+
_log.Error().Msg("Stopping services due to error")
183+
cancelSvc() // Cancel the service context to stop all services
184+
}
182185
}
183186
}
184187
}()

cmd/healthcheck/main.go

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@ type HealthStatus struct {
2222
}
2323

2424
func main() {
25-
var configPath string
25+
var (
26+
configPath string
27+
isBasicCheck bool
28+
debug bool
29+
)
2630
flag.StringVar(&configPath, "config", "/data", "path to the data folder")
31+
flag.BoolVar(&isBasicCheck, "basic", false, "perform basic health check without WebDAV")
32+
flag.BoolVar(&debug, "debug", false, "enable debug mode for detailed output")
2733
flag.Parse()
2834
config.SetConfigPath(configPath)
2935
cfg := config.Get()
@@ -63,16 +69,17 @@ func main() {
6369
status.WebUI = true
6470
}
6571

66-
// Check WebDAV if enabled
67-
if webdavPath != "" {
68-
if checkWebDAV(ctx, baseUrl, port, webdavPath) {
72+
if isBasicCheck {
73+
status.WebDAVService = checkBaseWebdav(ctx, baseUrl, port)
74+
} else {
75+
// If not a basic check, check WebDAV with debrid path
76+
if webdavPath != "" {
77+
status.WebDAVService = checkDebridWebDAV(ctx, baseUrl, port, webdavPath)
78+
} else {
79+
// If no WebDAV path is set, consider it healthy
6980
status.WebDAVService = true
7081
}
71-
} else {
72-
// If WebDAV is not enabled, consider it healthy
73-
status.WebDAVService = true
7482
}
75-
7683
// Determine overall status
7784
// Consider the application healthy if core services are running
7885
status.OverallStatus = status.QbitAPI && status.WebUI
@@ -81,7 +88,7 @@ func main() {
8188
}
8289

8390
// Optional: output health status as JSON for logging
84-
if os.Getenv("DEBUG") == "true" {
91+
if debug {
8592
statusJSON, _ := json.MarshalIndent(status, "", " ")
8693
fmt.Println(string(statusJSON))
8794
}
@@ -132,7 +139,24 @@ func checkWebUI(ctx context.Context, baseUrl, port string) bool {
132139
return resp.StatusCode == http.StatusOK
133140
}
134141

135-
func checkWebDAV(ctx context.Context, baseUrl, port, path string) bool {
142+
func checkBaseWebdav(ctx context.Context, baseUrl, port string) bool {
143+
url := fmt.Sprintf("http://localhost:%s%swebdav/", port, baseUrl)
144+
req, err := http.NewRequestWithContext(ctx, "PROPFIND", url, nil)
145+
if err != nil {
146+
return false
147+
}
148+
149+
resp, err := http.DefaultClient.Do(req)
150+
if err != nil {
151+
return false
152+
}
153+
defer resp.Body.Close()
154+
155+
return resp.StatusCode == http.StatusMultiStatus ||
156+
resp.StatusCode == http.StatusOK
157+
}
158+
159+
func checkDebridWebDAV(ctx context.Context, baseUrl, port, path string) bool {
136160
url := fmt.Sprintf("http://localhost:%s%swebdav/%s", port, baseUrl, path)
137161
req, err := http.NewRequestWithContext(ctx, "PROPFIND", url, nil)
138162
if err != nil {
@@ -145,5 +169,7 @@ func checkWebDAV(ctx context.Context, baseUrl, port, path string) bool {
145169
}
146170
defer resp.Body.Close()
147171

148-
return resp.StatusCode == 207 || resp.StatusCode == http.StatusOK
172+
return resp.StatusCode == http.StatusMultiStatus ||
173+
resp.StatusCode == http.StatusOK
174+
149175
}

docs/docs/configuration/general.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Here are the fundamental configuration options:
1414
"discord_webhook_url": "",
1515
"min_file_size": 0,
1616
"max_file_size": 0,
17-
"allowed_file_types": [".mp4", ".mkv", ".avi", ...],
17+
"allowed_file_types": ["mp4", "mkv", "avi", ...],
1818

1919
}
2020
```
@@ -55,18 +55,18 @@ When enabled, you'll need to provide a username and password to access the Decyp
5555

5656
You can set minimum and maximum file size limits for torrents:
5757
```json
58-
"min_file_size": 0, // Minimum file size in bytes (0 = no minimum)
59-
"max_file_size": 0 // Maximum file size in bytes (0 = no maximum)
58+
"min_file_size": 0,
59+
"max_file_size": 0
6060
```
6161

6262
#### Allowed File Types
6363
You can restrict the types of files that Decypharr will process by specifying allowed file extensions. This is useful for filtering out unwanted file types.
6464

6565
```json
6666
"allowed_file_types": [
67-
".mp4", ".mkv", ".avi", ".mov",
68-
".m4v", ".mpg", ".mpeg", ".wmv",
69-
".m4a", ".mp3", ".flac", ".wav"
67+
"mp4", "mkv", "avi", "mov",
68+
"m4v", "mpg", "mpeg", "wmv",
69+
"m4a", "mp3", "flac", "wav"
7070
]
7171
```
7272

0 commit comments

Comments
 (0)