- Fix url escape for webdav files

- Add support for bind address, url base
This commit is contained in:
Mukhtar Akere
2025-04-17 15:26:58 +01:00
parent b5b6f0ff73
commit 80615e06d1
10 changed files with 115 additions and 50 deletions

View File

@@ -7,6 +7,7 @@ import (
"github.com/sirrobot01/decypharr/pkg/debrid/types"
"io"
"net/http"
"net/url"
"os"
"sort"
"strings"
@@ -22,7 +23,8 @@ type fileInfo struct {
isDir bool
}
func (fi *fileInfo) Name() string { return fi.name }
func (fi *fileInfo) Name() string { return url.PathEscape(fi.name) }
func (fi *fileInfo) RawName() string { return fi.name }
func (fi *fileInfo) Size() int64 { return fi.size }
func (fi *fileInfo) Mode() os.FileMode { return fi.mode }
func (fi *fileInfo) ModTime() time.Time { return fi.modTime }

View File

@@ -25,7 +25,7 @@ type QBit struct {
func New() *QBit {
_cfg := config.Get()
cfg := _cfg.QBitTorrent
port := cmp.Or(cfg.Port, os.Getenv("QBIT_PORT"), "8282")
port := cmp.Or(_cfg.Port, os.Getenv("QBIT_PORT"), "8282")
refreshInterval := cmp.Or(cfg.RefreshInterval, 10)
return &QBit{
Username: cfg.Username,

View File

@@ -1,7 +1,6 @@
package server
import (
"cmp"
"context"
"errors"
"fmt"
@@ -15,6 +14,7 @@ import (
"net/http"
"os"
"os/signal"
path "path/filepath"
"runtime"
"syscall"
)
@@ -24,32 +24,47 @@ type Server struct {
logger zerolog.Logger
}
func New() *Server {
func New(handlers map[string]http.Handler) *Server {
l := logger.New("http")
r := chi.NewRouter()
r.Use(middleware.Recoverer)
r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
return &Server{
router: r,
cfg := config.Get()
s := &Server{
logger: l,
}
r.Handle(path.Join(cfg.URLBase, "static")+"/*",
http.StripPrefix(path.Join(cfg.URLBase, "static"), http.FileServer(http.Dir("static"))),
)
r.Route(cfg.URLBase, func(r chi.Router) {
for pattern, handler := range handlers {
r.Mount(pattern, handler)
}
//logs
r.Get("/logs", s.getLogs)
//stats
r.Get("/stats", s.getStats)
//webhooks
r.Post("/webhooks/tautulli", s.handleTautulli)
})
s.router = r
return s
}
func (s *Server) Start(ctx context.Context) error {
cfg := config.Get()
// Register routes
// Register webhooks
s.router.Post("/webhooks/tautulli", s.handleTautulli)
// Register logs
s.router.Get("/logs", s.getLogs)
s.router.Get("/stats", s.getStats)
p := cmp.Or(cfg.QBitTorrent.Port, "8282")
port := fmt.Sprintf(":%s", p)
s.logger.Info().Msgf("Server started on %s", port)
addr := fmt.Sprintf("%s:%s", cfg.BindAddress, cfg.Port)
s.logger.Info().Msgf("Starting server on %s%s", addr, cfg.URLBase)
srv := &http.Server{
Addr: port,
Addr: addr,
Handler: s.router,
}
@@ -68,10 +83,6 @@ func (s *Server) Start(ctx context.Context) error {
return srv.Shutdown(context.Background())
}
func (s *Server) AddRoutes(routes func(r chi.Router) http.Handler) {
routes(s.router)
}
func (s *Server) Mount(pattern string, handler http.Handler) {
s.router.Mount(pattern, handler)
}

View File

@@ -33,6 +33,42 @@
Open Magnet Links in Decypharr
</div>
</div>
<div class="col-md-6 mt-3">
<div class="form-group">
<label for="urlBase">URL Base</label>
<input type="text"
disabled
class="form-control"
id="urlBase"
name="url_base"
placeholder="/">
<small class="form-text text-muted">URL base for the application</small>
</div>
</div>
<div class="col-md-4 mt-3">
<div class="form-group">
<label for="bindAddress">Bind Address</label>
<input type="text"
disabled
class="form-control"
id="bindAddress"
name="bind_address"
placeholder="">
<small class="form-text text-muted">Bind address for the application(default is all interface)</small>
</div>
</div>
<div class="col-md-2 mt-3">
<div class="form-group">
<label for="port">Port</label>
<input type="text"
disabled
class="form-control"
id="port"
name="port"
placeholder="8282">
<small class="form-text text-muted">Port</small>
</div>
</div>
<div class="col-md-6 mt-3">
<div class="form-group">
<label for="discordWebhookUrl">Discord Webhook URL</label>
@@ -69,7 +105,6 @@
<small class="form-text text-muted">Minimum file size to download (0 for no limit)</small>
</div>
</div>
<div class="col-md-6 mt-3">
<div class="form-group">
<label for="maxFileSize">Maximum File Size</label>
@@ -106,10 +141,6 @@
<label class="form-label" for="qbit.password">Password</label>
<input type="password" class="form-control" name="qbit.password" id="qbit.password">
</div>
<div class="col-md-6 mb-3">
<label class="form-label" for="qbit.port">Port</label>
<input type="text" class="form-control" name="qbit.port" id="qbit.port" placeholder="e.g., 8080">
</div>
<div class="col-md-6 mb-3">
<label class="form-label" for="qbit.download_folder">Symlink/Download Folder</label>
<input type="text" class="form-control" name="qbit.download_folder" id="qbit.download_folder">
@@ -369,6 +400,15 @@
if (config.discord_webhook_url) {
document.querySelector('[name="discord_webhook_url"]').value = config.discord_webhook_url;
}
if (config.url_base) {
document.querySelector('[name="url_base"]').value = config.url_base;
}
if (config.bind_address) {
document.querySelector('[name="bind_address"]').value = config.bind_address;
}
if (config.port) {
document.querySelector('[name="port"]').value = config.port;
}
})
.catch(error => {
console.error('Error loading configuration:', error);
@@ -532,7 +572,6 @@
qbittorrent: {
username: document.querySelector('[name="qbit.username"]').value,
password: document.querySelector('[name="qbit.password"]').value,
port: document.querySelector('[name="qbit.port"]').value,
download_folder: document.querySelector('[name="qbit.download_folder"]').value,
refresh_interval: parseInt(document.querySelector('[name="qbit.refresh_interval"]').value || '0', 10)
},

View File

@@ -1,6 +1,7 @@
package webdav
import (
"net/url"
"os"
"time"
)
@@ -14,7 +15,8 @@ type FileInfo struct {
isDir bool
}
func (fi *FileInfo) Name() string { return fi.name }
func (fi *FileInfo) Name() string { return url.PathEscape(fi.name) }
func (fi *FileInfo) RawName() string { return fi.name }
func (fi *FileInfo) Size() int64 { return fi.size }
func (fi *FileInfo) Mode() os.FileMode { return fi.mode }
func (fi *FileInfo) ModTime() time.Time { return fi.modTime }

View File

@@ -14,7 +14,6 @@ import (
"io"
"net/http"
"net/http/httptest"
"net/url"
"os"
path "path/filepath"
"slices"
@@ -466,13 +465,6 @@ func (h *Handler) serveDirectory(w http.ResponseWriter, r *http.Request, file we
"add": func(a, b int) int {
return a + b
},
"urlpath": func(p string) string {
segments := strings.Split(p, "/")
for i, segment := range segments {
segments[i] = url.PathEscape(segment)
}
return strings.Join(segments, "/")
},
"formatSize": func(bytes int64) string {
const (
KB = 1024

View File

@@ -109,13 +109,13 @@ const directoryTemplate = `
<h1>Index of {{.Path}}</h1>
<ul>
{{if .ShowParent}}
<li><a href="{{urlpath .ParentPath}}" class="parent-dir"><span class="file-number"></span>Parent Directory</a></li>
<li><a href="{{ .ParentPath}}" class="parent-dir"><span class="file-number"></span>Parent Directory</a></li>
{{end}}
{{range $index, $file := .Children}}
<li>
<a href="{{urlpath (printf "%s/%s" $.Path $file.Name)}}">
<a href="{{(printf "%s/%s" $.Path $file.Name)}}">
<span class="file-number">{{add $index 1}}.</span>
<span class="file-name">{{$file.Name}}{{if $file.IsDir}}/{{end}}</span>
<span class="file-name">{{$file.RawName}}{{if $file.IsDir}}/{{end}}</span>
<span class="file-info">
{{if not $file.IsDir}}
{{formatSize $file.Size}}