- Fix url escape for webdav files
- Add support for bind address, url base
This commit is contained in:
@@ -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 }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}}
|
||||
|
||||
Reference in New Issue
Block a user