feat: restructure code; add size and ext checks (#39)
- Refractor code - Add file size and extension checkers - Change repair workflow to use zurg
This commit is contained in:
@@ -2,10 +2,10 @@ package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/utils"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/sirrobot01/debrid-blackhole/common"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/arr"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared"
|
||||
@@ -66,7 +66,7 @@ func (i *ImportRequest) Complete() {
|
||||
func (i *ImportRequest) Process(q *shared.QBit) (err error) {
|
||||
// Use this for now.
|
||||
// This sends the torrent to the arr
|
||||
magnet, err := common.GetMagnetFromUrl(i.URI)
|
||||
magnet, err := utils.GetMagnetFromUrl(i.URI)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing magnet link: %w", err)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/base64"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/sirrobot01/debrid-blackhole/common"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/request"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/arr"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared"
|
||||
"net/http"
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type qbitHandler struct {
|
||||
type QbitHandler struct {
|
||||
qbit *shared.QBit
|
||||
logger zerolog.Logger
|
||||
debug bool
|
||||
@@ -40,7 +40,7 @@ func decodeAuthHeader(header string) (string, string, error) {
|
||||
return host, token, nil
|
||||
}
|
||||
|
||||
func (q *qbitHandler) CategoryContext(next http.Handler) http.Handler {
|
||||
func (q *QbitHandler) CategoryContext(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
category := strings.Trim(r.URL.Query().Get("category"), "")
|
||||
if category == "" {
|
||||
@@ -59,7 +59,7 @@ func (q *qbitHandler) CategoryContext(next http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
func (q *qbitHandler) authContext(next http.Handler) http.Handler {
|
||||
func (q *QbitHandler) authContext(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
host, token, err := decodeAuthHeader(r.Header.Get("Authorization"))
|
||||
category := r.Context().Value("category").(string)
|
||||
@@ -96,29 +96,29 @@ func HashesCtx(next http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write([]byte("Ok."))
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleVersion(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleVersion(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write([]byte("v4.3.2"))
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleWebAPIVersion(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleWebAPIVersion(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write([]byte("2.7"))
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handlePreferences(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handlePreferences(w http.ResponseWriter, r *http.Request) {
|
||||
preferences := shared.NewAppPreferences()
|
||||
|
||||
preferences.WebUiUsername = q.qbit.Username
|
||||
preferences.SavePath = q.qbit.DownloadFolder
|
||||
preferences.TempPath = filepath.Join(q.qbit.DownloadFolder, "temp")
|
||||
|
||||
common.JSONResponse(w, preferences, http.StatusOK)
|
||||
request.JSONResponse(w, preferences, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleBuildInfo(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleBuildInfo(w http.ResponseWriter, r *http.Request) {
|
||||
res := shared.BuildInfo{
|
||||
Bitness: 64,
|
||||
Boost: "1.75.0",
|
||||
@@ -127,24 +127,24 @@ func (q *qbitHandler) handleBuildInfo(w http.ResponseWriter, r *http.Request) {
|
||||
Qt: "5.15.2",
|
||||
Zlib: "1.2.11",
|
||||
}
|
||||
common.JSONResponse(w, res, http.StatusOK)
|
||||
request.JSONResponse(w, res, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) shutdown(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) shutdown(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleTorrentsInfo(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleTorrentsInfo(w http.ResponseWriter, r *http.Request) {
|
||||
//log all url params
|
||||
ctx := r.Context()
|
||||
category := ctx.Value("category").(string)
|
||||
filter := strings.Trim(r.URL.Query().Get("filter"), "")
|
||||
hashes, _ := ctx.Value("hashes").([]string)
|
||||
torrents := q.qbit.Storage.GetAll(category, filter, hashes)
|
||||
common.JSONResponse(w, torrents, http.StatusOK)
|
||||
request.JSONResponse(w, torrents, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleTorrentsAdd(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleTorrentsAdd(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
// Parse form based on content type
|
||||
@@ -209,7 +209,7 @@ func (q *qbitHandler) handleTorrentsAdd(w http.ResponseWriter, r *http.Request)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleTorrentsDelete(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleTorrentsDelete(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
hashes, _ := ctx.Value("hashes").([]string)
|
||||
if len(hashes) == 0 {
|
||||
@@ -223,7 +223,7 @@ func (q *qbitHandler) handleTorrentsDelete(w http.ResponseWriter, r *http.Reques
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleTorrentsPause(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleTorrentsPause(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
hashes, _ := ctx.Value("hashes").([]string)
|
||||
for _, hash := range hashes {
|
||||
@@ -237,7 +237,7 @@ func (q *qbitHandler) handleTorrentsPause(w http.ResponseWriter, r *http.Request
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleTorrentsResume(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleTorrentsResume(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
hashes, _ := ctx.Value("hashes").([]string)
|
||||
for _, hash := range hashes {
|
||||
@@ -251,7 +251,7 @@ func (q *qbitHandler) handleTorrentsResume(w http.ResponseWriter, r *http.Reques
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleTorrentRecheck(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleTorrentRecheck(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
hashes, _ := ctx.Value("hashes").([]string)
|
||||
for _, hash := range hashes {
|
||||
@@ -265,7 +265,7 @@ func (q *qbitHandler) handleTorrentRecheck(w http.ResponseWriter, r *http.Reques
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleCategories(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleCategories(w http.ResponseWriter, r *http.Request) {
|
||||
var categories = map[string]shared.TorrentCategory{}
|
||||
for _, cat := range q.qbit.Categories {
|
||||
path := filepath.Join(q.qbit.DownloadFolder, cat)
|
||||
@@ -274,10 +274,10 @@ func (q *qbitHandler) handleCategories(w http.ResponseWriter, r *http.Request) {
|
||||
SavePath: path,
|
||||
}
|
||||
}
|
||||
common.JSONResponse(w, categories, http.StatusOK)
|
||||
request.JSONResponse(w, categories, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleCreateCategory(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleCreateCategory(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to parse form data", http.StatusBadRequest)
|
||||
@@ -292,27 +292,27 @@ func (q *qbitHandler) handleCreateCategory(w http.ResponseWriter, r *http.Reques
|
||||
|
||||
q.qbit.Categories = append(q.qbit.Categories, name)
|
||||
|
||||
common.JSONResponse(w, nil, http.StatusOK)
|
||||
request.JSONResponse(w, nil, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleTorrentProperties(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleTorrentProperties(w http.ResponseWriter, r *http.Request) {
|
||||
hash := r.URL.Query().Get("hash")
|
||||
torrent := q.qbit.Storage.Get(hash)
|
||||
properties := q.qbit.GetTorrentProperties(torrent)
|
||||
common.JSONResponse(w, properties, http.StatusOK)
|
||||
request.JSONResponse(w, properties, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleTorrentFiles(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleTorrentFiles(w http.ResponseWriter, r *http.Request) {
|
||||
hash := r.URL.Query().Get("hash")
|
||||
torrent := q.qbit.Storage.Get(hash)
|
||||
if torrent == nil {
|
||||
return
|
||||
}
|
||||
files := q.qbit.GetTorrentFiles(torrent)
|
||||
common.JSONResponse(w, files, http.StatusOK)
|
||||
request.JSONResponse(w, files, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleSetCategory(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleSetCategory(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
category := ctx.Value("category").(string)
|
||||
hashes, _ := ctx.Value("hashes").([]string)
|
||||
@@ -321,10 +321,10 @@ func (q *qbitHandler) handleSetCategory(w http.ResponseWriter, r *http.Request)
|
||||
torrent.Category = category
|
||||
q.qbit.Storage.AddOrUpdate(torrent)
|
||||
}
|
||||
common.JSONResponse(w, nil, http.StatusOK)
|
||||
request.JSONResponse(w, nil, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleAddTorrentTags(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleAddTorrentTags(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to parse form data", http.StatusBadRequest)
|
||||
@@ -340,10 +340,10 @@ func (q *qbitHandler) handleAddTorrentTags(w http.ResponseWriter, r *http.Reques
|
||||
for _, t := range torrents {
|
||||
q.qbit.SetTorrentTags(t, tags)
|
||||
}
|
||||
common.JSONResponse(w, nil, http.StatusOK)
|
||||
request.JSONResponse(w, nil, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleRemoveTorrentTags(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleRemoveTorrentTags(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to parse form data", http.StatusBadRequest)
|
||||
@@ -360,14 +360,14 @@ func (q *qbitHandler) handleRemoveTorrentTags(w http.ResponseWriter, r *http.Req
|
||||
q.qbit.RemoveTorrentTags(torrent, tags)
|
||||
|
||||
}
|
||||
common.JSONResponse(w, nil, http.StatusOK)
|
||||
request.JSONResponse(w, nil, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleGetTags(w http.ResponseWriter, r *http.Request) {
|
||||
common.JSONResponse(w, q.qbit.Tags, http.StatusOK)
|
||||
func (q *QbitHandler) handleGetTags(w http.ResponseWriter, r *http.Request) {
|
||||
request.JSONResponse(w, q.qbit.Tags, http.StatusOK)
|
||||
}
|
||||
|
||||
func (q *qbitHandler) handleCreateTags(w http.ResponseWriter, r *http.Request) {
|
||||
func (q *QbitHandler) handleCreateTags(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to parse form data", http.StatusBadRequest)
|
||||
@@ -378,5 +378,5 @@ func (q *qbitHandler) handleCreateTags(w http.ResponseWriter, r *http.Request) {
|
||||
tags[i] = strings.TrimSpace(tag)
|
||||
}
|
||||
q.qbit.AddTags(tags)
|
||||
common.JSONResponse(w, nil, http.StatusOK)
|
||||
request.JSONResponse(w, nil, http.StatusOK)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (q *qbitHandler) Routes(r chi.Router) http.Handler {
|
||||
func (q *QbitHandler) Routes(r chi.Router) http.Handler {
|
||||
r.Route("/api/v2", func(r chi.Router) {
|
||||
//if q.debug {
|
||||
// r.Use(middleware.Logger)
|
||||
|
||||
@@ -7,10 +7,12 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/sirrobot01/debrid-blackhole/common"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/config"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/logger"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/arr"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/repair"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -23,12 +25,13 @@ type Server struct {
|
||||
logger zerolog.Logger
|
||||
}
|
||||
|
||||
func NewServer(config *common.Config, deb *debrid.DebridService, arrs *arr.Storage) *Server {
|
||||
logger := common.NewLogger("QBit", config.QBitTorrent.LogLevel, os.Stdout)
|
||||
q := shared.NewQBit(config, deb, logger, arrs)
|
||||
func NewServer(deb *debrid.DebridService, arrs *arr.Storage, _repair *repair.Repair) *Server {
|
||||
cfg := config.GetConfig()
|
||||
l := logger.NewLogger("QBit", cfg.QBitTorrent.LogLevel, os.Stdout)
|
||||
q := shared.NewQBit(deb, l, arrs, _repair)
|
||||
return &Server{
|
||||
qbit: q,
|
||||
logger: logger,
|
||||
logger: l,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +41,12 @@ func (s *Server) Start(ctx context.Context) error {
|
||||
r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
||||
logLevel := s.logger.GetLevel().String()
|
||||
debug := logLevel == "debug"
|
||||
q := qbitHandler{qbit: s.qbit, logger: s.logger, debug: debug}
|
||||
ui := uiHandler{qbit: s.qbit, logger: common.NewLogger("UI", s.logger.GetLevel().String(), os.Stdout), debug: debug}
|
||||
q := QbitHandler{qbit: s.qbit, logger: s.logger, debug: debug}
|
||||
ui := UIHandler{
|
||||
qbit: s.qbit,
|
||||
logger: logger.NewLogger("UI", s.logger.GetLevel().String(), os.Stdout),
|
||||
debug: debug,
|
||||
}
|
||||
|
||||
// Register routes
|
||||
r.Get("/logs", s.GetLogs)
|
||||
@@ -71,7 +78,7 @@ func (s *Server) Start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (s *Server) GetLogs(w http.ResponseWriter, r *http.Request) {
|
||||
logFile := common.GetLogPath()
|
||||
logFile := logger.GetLogPath()
|
||||
|
||||
// Open and read the file
|
||||
file, err := os.Open(logFile)
|
||||
@@ -79,7 +86,12 @@ func (s *Server) GetLogs(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Error reading log file", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
defer func(file *os.File) {
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
s.logger.Debug().Err(err).Msg("Error closing log file")
|
||||
}
|
||||
}(file)
|
||||
|
||||
// Set headers
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
@@ -91,6 +103,7 @@ func (s *Server) GetLogs(w http.ResponseWriter, r *http.Request) {
|
||||
// Stream the file
|
||||
_, err = io.Copy(w, file)
|
||||
if err != nil {
|
||||
s.logger.Debug().Err(err).Msg("Error streaming log file")
|
||||
http.Error(w, "Error streaming log file", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -30,6 +30,45 @@
|
||||
Open Magnet Links in DecyphArr
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 mt-3">
|
||||
<div class="form-group">
|
||||
<label for="allowedExtensions">Allowed File Extensions</label>
|
||||
<div class="input-group">
|
||||
<textarea type="text"
|
||||
class="form-control"
|
||||
id="allowedExtensions"
|
||||
name="allowed_file_types"
|
||||
disabled
|
||||
placeholder="mkv, mp4, avi, etc.">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mt-3">
|
||||
<div class="form-group">
|
||||
<label for="minFileSize">Minimum File Size</label>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
id="minFileSize"
|
||||
name="min_file_size"
|
||||
disabled
|
||||
placeholder="e.g., 10MB, 1GB">
|
||||
<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>
|
||||
<input type="text"
|
||||
class="form-control"
|
||||
id="maxFileSize"
|
||||
name="max_file_size"
|
||||
disabled
|
||||
placeholder="e.g., 50GB, 100MB">
|
||||
<small class="form-text text-muted">Maximum file size to download (0 for no limit)</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Debrid Configuration -->
|
||||
@@ -216,6 +255,15 @@
|
||||
|
||||
const logLevel = document.getElementById('log-level');
|
||||
logLevel.value = config.log_level;
|
||||
if (config.allowed_file_types && Array.isArray(config.allowed_file_types)) {
|
||||
document.querySelector('[name="allowed_file_types"]').value = config.allowed_file_types.join(', ');
|
||||
}
|
||||
if (config.min_file_size) {
|
||||
document.querySelector('[name="min_file_size"]').value = config.min_file_size;
|
||||
}
|
||||
if (config.max_file_size) {
|
||||
document.querySelector('[name="max_file_size"]').value = config.max_file_size;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -3,15 +3,16 @@ package server
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/config"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/request"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/utils"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/sirrobot01/debrid-blackhole/common"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/arr"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/qbit/shared"
|
||||
@@ -49,7 +50,7 @@ type RepairRequest struct {
|
||||
//go:embed templates/*
|
||||
var content embed.FS
|
||||
|
||||
type uiHandler struct {
|
||||
type UIHandler struct {
|
||||
qbit *shared.QBit
|
||||
logger zerolog.Logger
|
||||
debug bool
|
||||
@@ -68,7 +69,7 @@ func init() {
|
||||
))
|
||||
}
|
||||
|
||||
func (u *uiHandler) IndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func (u *UIHandler) IndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data := map[string]interface{}{
|
||||
"Page": "index",
|
||||
"Title": "Torrents",
|
||||
@@ -79,7 +80,7 @@ func (u *uiHandler) IndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func (u *uiHandler) DownloadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func (u *UIHandler) DownloadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data := map[string]interface{}{
|
||||
"Page": "download",
|
||||
"Title": "Download",
|
||||
@@ -90,7 +91,7 @@ func (u *uiHandler) DownloadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func (u *uiHandler) RepairHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func (u *UIHandler) RepairHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data := map[string]interface{}{
|
||||
"Page": "repair",
|
||||
"Title": "Repair",
|
||||
@@ -101,7 +102,7 @@ func (u *uiHandler) RepairHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func (u *uiHandler) ConfigHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func (u *UIHandler) ConfigHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data := map[string]interface{}{
|
||||
"Page": "config",
|
||||
"Title": "Config",
|
||||
@@ -112,11 +113,11 @@ func (u *uiHandler) ConfigHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func (u *uiHandler) handleGetArrs(w http.ResponseWriter, r *http.Request) {
|
||||
common.JSONResponse(w, u.qbit.Arrs.GetAll(), http.StatusOK)
|
||||
func (u *UIHandler) handleGetArrs(w http.ResponseWriter, r *http.Request) {
|
||||
request.JSONResponse(w, u.qbit.Arrs.GetAll(), http.StatusOK)
|
||||
}
|
||||
|
||||
func (u *uiHandler) handleAddContent(w http.ResponseWriter, r *http.Request) {
|
||||
func (u *UIHandler) handleAddContent(w http.ResponseWriter, r *http.Request) {
|
||||
if err := r.ParseMultipartForm(32 << 20); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
@@ -162,7 +163,7 @@ func (u *uiHandler) handleAddContent(w http.ResponseWriter, r *http.Request) {
|
||||
continue
|
||||
}
|
||||
|
||||
magnet, err := common.GetMagnetFromFile(file, fileHeader.Filename)
|
||||
magnet, err := utils.GetMagnetFromFile(file, fileHeader.Filename)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Sprintf("Failed to parse torrent file %s: %v", fileHeader.Filename, err))
|
||||
continue
|
||||
@@ -178,7 +179,7 @@ func (u *uiHandler) handleAddContent(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
common.JSONResponse(w, struct {
|
||||
request.JSONResponse(w, struct {
|
||||
Results []*ImportRequest `json:"results"`
|
||||
Errors []string `json:"errors,omitempty"`
|
||||
}{
|
||||
@@ -187,7 +188,7 @@ func (u *uiHandler) handleAddContent(w http.ResponseWriter, r *http.Request) {
|
||||
}, http.StatusOK)
|
||||
}
|
||||
|
||||
func (u *uiHandler) handleCheckCached(w http.ResponseWriter, r *http.Request) {
|
||||
func (u *UIHandler) handleCheckCached(w http.ResponseWriter, r *http.Request) {
|
||||
_hashes := r.URL.Query().Get("hash")
|
||||
if _hashes == "" {
|
||||
http.Error(w, "No hashes provided", http.StatusBadRequest)
|
||||
@@ -216,10 +217,10 @@ func (u *uiHandler) handleCheckCached(w http.ResponseWriter, r *http.Request) {
|
||||
_, exists := res[h]
|
||||
result[h] = exists
|
||||
}
|
||||
common.JSONResponse(w, result, http.StatusOK)
|
||||
request.JSONResponse(w, result, http.StatusOK)
|
||||
}
|
||||
|
||||
func (u *uiHandler) handleRepairMedia(w http.ResponseWriter, r *http.Request) {
|
||||
func (u *UIHandler) handleRepairMedia(w http.ResponseWriter, r *http.Request) {
|
||||
var req RepairRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
@@ -232,50 +233,35 @@ func (u *uiHandler) handleRepairMedia(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
mediaIds := req.MediaIds
|
||||
if len(mediaIds) == 0 {
|
||||
mediaIds = []string{""}
|
||||
}
|
||||
|
||||
if req.Async {
|
||||
for _, tvId := range mediaIds {
|
||||
go func() {
|
||||
err := _arr.Repair(tvId)
|
||||
if err != nil {
|
||||
u.logger.Info().Msgf("Failed to repair: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
common.JSONResponse(w, "Repair process started", http.StatusOK)
|
||||
go func() {
|
||||
if err := u.qbit.Repair.Repair([]*arr.Arr{_arr}, req.MediaIds); err != nil {
|
||||
u.logger.Error().Err(err).Msg("Failed to repair media")
|
||||
}
|
||||
}()
|
||||
request.JSONResponse(w, "Repair process started", http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
var errs []error
|
||||
for _, tvId := range mediaIds {
|
||||
if err := _arr.Repair(tvId); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
combinedErr := errors.Join(errs...)
|
||||
http.Error(w, fmt.Sprintf("Failed to repair: %v", combinedErr), http.StatusInternalServerError)
|
||||
if err := u.qbit.Repair.Repair([]*arr.Arr{_arr}, req.MediaIds); err != nil {
|
||||
http.Error(w, fmt.Sprintf("Failed to repair: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
common.JSONResponse(w, "Repair completed", http.StatusOK)
|
||||
request.JSONResponse(w, "Repair completed", http.StatusOK)
|
||||
}
|
||||
|
||||
func (u *uiHandler) handleGetVersion(w http.ResponseWriter, r *http.Request) {
|
||||
func (u *UIHandler) handleGetVersion(w http.ResponseWriter, r *http.Request) {
|
||||
v := version.GetInfo()
|
||||
common.JSONResponse(w, v, http.StatusOK)
|
||||
request.JSONResponse(w, v, http.StatusOK)
|
||||
}
|
||||
|
||||
func (u *uiHandler) handleGetTorrents(w http.ResponseWriter, r *http.Request) {
|
||||
common.JSONResponse(w, u.qbit.Storage.GetAll("", "", nil), http.StatusOK)
|
||||
func (u *UIHandler) handleGetTorrents(w http.ResponseWriter, r *http.Request) {
|
||||
request.JSONResponse(w, u.qbit.Storage.GetAll("", "", nil), http.StatusOK)
|
||||
}
|
||||
|
||||
func (u *uiHandler) handleDeleteTorrent(w http.ResponseWriter, r *http.Request) {
|
||||
func (u *UIHandler) handleDeleteTorrent(w http.ResponseWriter, r *http.Request) {
|
||||
hash := chi.URLParam(r, "hash")
|
||||
if hash == "" {
|
||||
http.Error(w, "No hash provided", http.StatusBadRequest)
|
||||
@@ -285,12 +271,12 @@ func (u *uiHandler) handleDeleteTorrent(w http.ResponseWriter, r *http.Request)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func (u *uiHandler) handleGetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config := common.CONFIG
|
||||
arrCfgs := make([]common.ArrConfig, 0)
|
||||
func (u *UIHandler) handleGetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
cfg := config.GetConfig()
|
||||
arrCfgs := make([]config.Arr, 0)
|
||||
for _, a := range u.qbit.Arrs.GetAll() {
|
||||
arrCfgs = append(arrCfgs, common.ArrConfig{Host: a.Host, Name: a.Name, Token: a.Token})
|
||||
arrCfgs = append(arrCfgs, config.Arr{Host: a.Host, Name: a.Name, Token: a.Token})
|
||||
}
|
||||
config.Arrs = arrCfgs
|
||||
common.JSONResponse(w, config, http.StatusOK)
|
||||
cfg.Arrs = arrCfgs
|
||||
request.JSONResponse(w, cfg, http.StatusOK)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (u *uiHandler) Routes(r chi.Router) http.Handler {
|
||||
func (u *UIHandler) Routes(r chi.Router) http.Handler {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Get("/", u.IndexHandler)
|
||||
r.Get("/download", u.DownloadHandler)
|
||||
|
||||
Reference in New Issue
Block a user