Add logs route, add rar handler

This commit is contained in:
Ben Sarmiento
2023-12-06 19:18:04 +01:00
parent 2a0b0fa9cd
commit 2aacff1125
19 changed files with 151 additions and 44 deletions

View File

@@ -4,6 +4,7 @@ import (
"fmt"
netHttp "net/http"
"os"
"time"
// _ "net/http/pprof" // Register pprof
@@ -20,7 +21,9 @@ import (
)
func MainApp(configPath string) {
log := logutil.NewLogger()
utils.EnsureDirExists("logs") // Ensure the logs directory exists
logPath := fmt.Sprintf("logs/zurg-%s.log", time.Now().Format(time.DateOnly))
log := logutil.NewLogger(logPath)
zurglog := log.Named("zurg")
zurglog.Debugf("PID: %d", os.Getpid())
@@ -42,8 +45,7 @@ func MainApp(configPath string) {
}
defer p.Release()
utils.EnsureDirExists("data")
utils.EnsureDirExists("data") // Ensure the data directory exists
torrentMgr := torrent.NewTorrentManager(config, rd, p, log.Named("manager"))
downloadClient := http.NewHTTPClient(config.GetToken(), config.GetRetriesUntilFailed(), 0, config, log.Named("dlclient"))

View File

@@ -4,11 +4,11 @@ import (
"fmt"
"os"
"go.uber.org/zap"
"github.com/debridmediamanager/zurg/pkg/logutil"
"gopkg.in/yaml.v3"
)
func LoadZurgConfig(filename string, log *zap.SugaredLogger) (ConfigInterface, error) {
func LoadZurgConfig(filename string, log *logutil.Logger) (ConfigInterface, error) {
log.Debug("Loading config file ", filename)
content, err := os.ReadFile(filename)
if err != nil {

View File

@@ -24,6 +24,7 @@ type ConfigInterface interface {
GetRetriesUntilFailed() int
EnableDownloadCache() bool
GetRateLimitSleepSeconds() int
ShouldDeleteRarFiles() bool
}
type ZurgConfig struct {
@@ -45,6 +46,7 @@ type ZurgConfig struct {
RealDebridTimeout int `yaml:"realdebrid_timeout_secs" json:"realdebrid_timeout_secs"`
RetriesUntilFailed int `yaml:"retries_until_failed" json:"retries_until_failed"`
UseDownloadCache bool `yaml:"use_download_cache" json:"use_download_cache"`
DeleteRarFiles bool `yaml:"delete_rar_files" json:"delete_rar_files"`
}
func (z *ZurgConfig) GetConfig() ZurgConfig {
@@ -146,3 +148,7 @@ func (z *ZurgConfig) GetRateLimitSleepSeconds() int {
}
return z.RateLimitSleepSeconds
}
func (z *ZurgConfig) ShouldDeleteRarFiles() bool {
return z.DeleteRarFiles
}

View File

@@ -7,8 +7,8 @@ import (
"strconv"
"strings"
"github.com/debridmediamanager/zurg/pkg/logutil"
"github.com/debridmediamanager/zurg/pkg/utils"
"go.uber.org/zap"
"gopkg.in/yaml.v3"
)
@@ -16,7 +16,7 @@ const (
ALL_TORRENTS = "__all__"
)
func loadV1Config(content []byte, log *zap.SugaredLogger) (*ZurgConfigV1, error) {
func loadV1Config(content []byte, log *logutil.Logger) (*ZurgConfigV1, error) {
var configV1 ZurgConfigV1
if err := yaml.Unmarshal(content, &configV1); err != nil {
return nil, err

View File

@@ -1,11 +1,11 @@
package config
import "go.uber.org/zap"
import "github.com/debridmediamanager/zurg/pkg/logutil"
type ZurgConfigV1 struct {
ZurgConfig `yaml:",inline"`
Directories map[string]*DirectoryFilterConditionsV1 `yaml:"directories"`
log *zap.SugaredLogger
log *logutil.Logger
}
type DirectoryFilterConditionsV1 struct {
GroupOrder int `yaml:"group_order"`

View File

@@ -8,7 +8,7 @@ import (
"github.com/debridmediamanager/zurg/internal/torrent"
"github.com/debridmediamanager/zurg/pkg/dav"
"go.uber.org/zap"
"github.com/debridmediamanager/zurg/pkg/logutil"
)
func HandleListDirectories(torMgr *torrent.TorrentManager) (*string, error) {
@@ -26,7 +26,7 @@ func HandleListDirectories(torMgr *torrent.TorrentManager) (*string, error) {
return &davDoc, nil
}
func HandleListTorrents(directory string, torMgr *torrent.TorrentManager, log *zap.SugaredLogger) (*string, error) {
func HandleListTorrents(directory string, torMgr *torrent.TorrentManager, log *logutil.Logger) (*string, error) {
torrents, ok := torMgr.DirectoryMap.Get(directory)
if !ok {
return nil, fmt.Errorf("cannot find directory %s", directory)
@@ -51,7 +51,7 @@ func HandleListTorrents(directory string, torMgr *torrent.TorrentManager, log *z
return &davDoc, nil
}
func HandleListFiles(directory, torrentName string, torMgr *torrent.TorrentManager, log *zap.SugaredLogger) (*string, error) {
func HandleListFiles(directory, torrentName string, torMgr *torrent.TorrentManager, log *logutil.Logger) (*string, error) {
torrents, ok := torMgr.DirectoryMap.Get(directory)
if !ok {
return nil, fmt.Errorf("cannot find directory %s", directory)

View File

@@ -8,7 +8,7 @@ import (
"strings"
"github.com/debridmediamanager/zurg/internal/torrent"
"go.uber.org/zap"
"github.com/debridmediamanager/zurg/pkg/logutil"
)
func HandleListDirectories(torMgr *torrent.TorrentManager) (*string, error) {
@@ -26,7 +26,7 @@ func HandleListDirectories(torMgr *torrent.TorrentManager) (*string, error) {
return &htmlDoc, nil
}
func HandleListTorrents(directory string, torMgr *torrent.TorrentManager, log *zap.SugaredLogger) (*string, error) {
func HandleListTorrents(directory string, torMgr *torrent.TorrentManager, log *logutil.Logger) (*string, error) {
torrents, ok := torMgr.DirectoryMap.Get(directory)
if !ok {
return nil, fmt.Errorf("cannot find directory %s", directory)
@@ -49,7 +49,7 @@ func HandleListTorrents(directory string, torMgr *torrent.TorrentManager, log *z
return &htmlDoc, nil
}
func HandleListFiles(directory, torrentName string, torMgr *torrent.TorrentManager, log *zap.SugaredLogger) (*string, error) {
func HandleListFiles(directory, torrentName string, torMgr *torrent.TorrentManager, log *logutil.Logger) (*string, error) {
torrents, ok := torMgr.DirectoryMap.Get(directory)
if !ok {
return nil, fmt.Errorf("cannot find directory %s", directory)

View File

@@ -12,9 +12,9 @@ import (
"github.com/debridmediamanager/zurg/internal/torrent"
"github.com/debridmediamanager/zurg/internal/universal"
"github.com/debridmediamanager/zurg/internal/version"
"github.com/debridmediamanager/zurg/pkg/logutil"
"github.com/debridmediamanager/zurg/pkg/realdebrid"
"github.com/julienschmidt/httprouter"
"go.uber.org/zap"
jsoniter "github.com/json-iterator/go"
)
@@ -26,10 +26,10 @@ type ZurgRouter struct {
torMgr *torrent.TorrentManager
cfg config.ConfigInterface
api *realdebrid.RealDebrid
log *zap.SugaredLogger
log *logutil.Logger
}
func ApplyRouteTable(router *httprouter.Router, getfile *universal.GetFile, torMgr *torrent.TorrentManager, cfg config.ConfigInterface, api *realdebrid.RealDebrid, log *zap.SugaredLogger) {
func ApplyRouteTable(router *httprouter.Router, getfile *universal.GetFile, torMgr *torrent.TorrentManager, cfg config.ConfigInterface, api *realdebrid.RealDebrid, log *logutil.Logger) {
zr := &ZurgRouter{
getfile: getfile,
torMgr: torMgr,
@@ -64,6 +64,10 @@ func ApplyRouteTable(router *httprouter.Router, getfile *universal.GetFile, torM
// root route
router.GET("/", zr.rootHandler)
// logs route
router.GET("/logs", zr.logsHandler)
router.GET("/logs/", zr.logsHandler)
}
func (zr *ZurgRouter) httpTorrentDirectoryHandler(resp http.ResponseWriter, req *http.Request, params httprouter.Params) {
@@ -233,6 +237,15 @@ func (zr *ZurgRouter) rootHandler(resp http.ResponseWriter, req *http.Request, p
}
}
func (zr *ZurgRouter) logsHandler(resp http.ResponseWriter, req *http.Request, params httprouter.Params) {
logs, err := zr.log.GetLogsFromFile()
if err != nil {
http.Error(resp, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprint(resp, logs)
}
func bToMb(b uint64) uint64 {
return b / 1024 / 1024
}

View File

@@ -6,7 +6,7 @@ import (
"os/exec"
"github.com/debridmediamanager/zurg/internal/config"
"go.uber.org/zap"
"github.com/debridmediamanager/zurg/pkg/logutil"
)
type ScriptExecutor struct {
@@ -32,7 +32,7 @@ func (se *ScriptExecutor) Execute() (string, error) {
return out.String(), nil
}
func OnLibraryUpdateHook(paths []string, config config.ConfigInterface, log *zap.SugaredLogger) {
func OnLibraryUpdateHook(paths []string, config config.ConfigInterface, log *logutil.Logger) {
executor := &ScriptExecutor{
Script: config.GetOnLibraryUpdate(),
Args: paths,

View File

@@ -7,12 +7,12 @@ import (
"strings"
"github.com/debridmediamanager/zurg/internal/config"
"github.com/debridmediamanager/zurg/pkg/logutil"
"github.com/debridmediamanager/zurg/pkg/realdebrid"
cmap "github.com/orcaman/concurrent-map/v2"
"github.com/panjf2000/ants/v2"
"github.com/scylladb/go-set"
"github.com/scylladb/go-set/strset"
"go.uber.org/zap"
)
const (
@@ -30,13 +30,13 @@ type TorrentManager struct {
requiredVersion string
workerPool *ants.Pool
repairWorker *ants.Pool
log *zap.SugaredLogger
log *logutil.Logger
}
// NewTorrentManager creates a new torrent manager
// it will fetch all torrents and their info in the background
// and store them in-memory and cached in files
func NewTorrentManager(cfg config.ConfigInterface, api *realdebrid.RealDebrid, p *ants.Pool, log *zap.SugaredLogger) *TorrentManager {
func NewTorrentManager(cfg config.ConfigInterface, api *realdebrid.RealDebrid, p *ants.Pool, log *logutil.Logger) *TorrentManager {
initialSate := EmptyState()
t := &TorrentManager{

View File

@@ -149,8 +149,26 @@ func (t *TorrentManager) getMoreInfo(rdTorrent realdebrid.Torrent) *Torrent {
})
}
if len(selectedFiles) > len(info.Links) && info.Progress == 100 {
t.log.Warnf("Torrent id=%s is partly expired, it has %d selected files but only %d links", info.ID, len(selectedFiles), len(info.Links))
torrent.ForRepair = true
if len(info.Links) == 1 {
// this might be a rar file so let's check
unrestrict := t.UnrestrictUntilOk(info.Links[0])
if unrestrict != nil && strings.HasPrefix(strings.ToLower(unrestrict.Filename), ".rar") {
if t.Config.ShouldDeleteRarFiles() {
t.log.Warnf("Torrent %s id=%s is a rar file, it cannot be repaired. Deleting...", info.Name, info.ID)
t.Api.DeleteTorrent(info.ID)
return nil
} else {
t.log.Warnf("Torrent %s id=%s is a rar file, it cannot be repaired as it's a known Real-Debrid limitation. zurg recommends you delete this torrent or enable delete_rar_files in your config.yml", info.Name, info.ID)
torrent.Unfixable = true
}
} else {
t.log.Warnf("Torrent id=%s is partly expired. It has %d selected files but only 1 link", info.ID, len(selectedFiles), len(info.Links))
torrent.ForRepair = true
}
} else {
t.log.Warnf("Torrent id=%s is partly expired. It has %d selected files but only %d links", info.ID, len(selectedFiles), len(info.Links))
torrent.ForRepair = true
}
} else if len(selectedFiles) == len(info.Links) {
// all links are still intact! good!
for i, file := range selectedFiles {

View File

@@ -22,7 +22,7 @@ func (t *TorrentManager) repairAll() {
if torrent.AnyInProgress() && torrent.ForRepair {
t.log.Warnf("Skipping %s for repairs because it is in progress", torrent.AccessKey)
return
} else if torrent.ForRepair {
} else if torrent.ForRepair && !torrent.Unfixable {
toRepair = append(toRepair, torrent)
}
})

View File

@@ -18,6 +18,7 @@ type Torrent struct {
SelectedFiles cmap.ConcurrentMap[string, *File] `json:"-"`
LatestAdded string `json:"LatestAdded"`
ForRepair bool `json:"ForRepair"`
Unfixable bool `json:"Unfixable"`
DownloadedIDs *strset.Set `json:"DownloadedIDs"`
InProgressIDs *strset.Set `json:"InProgressIDs"`

View File

@@ -11,8 +11,8 @@ import (
"github.com/debridmediamanager/zurg/internal/config"
intTor "github.com/debridmediamanager/zurg/internal/torrent"
zurghttp "github.com/debridmediamanager/zurg/pkg/http"
"github.com/debridmediamanager/zurg/pkg/logutil"
"github.com/debridmediamanager/zurg/pkg/realdebrid"
"go.uber.org/zap"
)
type GetFile struct {
@@ -24,7 +24,7 @@ func NewGetFile(client *zurghttp.HTTPClient) *GetFile {
}
// HandleGetRequest handles a GET request universally for both WebDAV and HTTP
func (gf *GetFile) HandleGetRequest(directory, torrentName, fileName string, resp http.ResponseWriter, req *http.Request, torMgr *intTor.TorrentManager, cfg config.ConfigInterface, log *zap.SugaredLogger) {
func (gf *GetFile) HandleGetRequest(directory, torrentName, fileName string, resp http.ResponseWriter, req *http.Request, torMgr *intTor.TorrentManager, cfg config.ConfigInterface, log *logutil.Logger) {
torrents, ok := torMgr.DirectoryMap.Get(directory)
if !ok {
log.Warnf("Cannot find directory %s", directory)
@@ -96,7 +96,7 @@ func (gf *GetFile) HandleGetRequest(directory, torrentName, fileName string, res
}
}
func (gf *GetFile) streamCachedLinkToResponse(url string, resp http.ResponseWriter, req *http.Request, torMgr *intTor.TorrentManager, cfg config.ConfigInterface, log *zap.SugaredLogger) error {
func (gf *GetFile) streamCachedLinkToResponse(url string, resp http.ResponseWriter, req *http.Request, torMgr *intTor.TorrentManager, cfg config.ConfigInterface, log *logutil.Logger) error {
// Create a new dlReq for the file download.
dlReq, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
@@ -129,7 +129,7 @@ func (gf *GetFile) streamCachedLinkToResponse(url string, resp http.ResponseWrit
return nil
}
func (gf *GetFile) streamFileToResponse(torrent *intTor.Torrent, file *intTor.File, unrestrict *realdebrid.Download, resp http.ResponseWriter, req *http.Request, torMgr *intTor.TorrentManager, cfg config.ConfigInterface, log *zap.SugaredLogger) {
func (gf *GetFile) streamFileToResponse(torrent *intTor.Torrent, file *intTor.File, unrestrict *realdebrid.Download, resp http.ResponseWriter, req *http.Request, torMgr *intTor.TorrentManager, cfg config.ConfigInterface, log *logutil.Logger) {
// Create a new request for the file download.
dlReq, err := http.NewRequest(http.MethodGet, unrestrict.Download, nil)
if err != nil {

View File

@@ -7,10 +7,10 @@ import (
"strings"
"github.com/debridmediamanager/zurg/internal/torrent"
"go.uber.org/zap"
"github.com/debridmediamanager/zurg/pkg/logutil"
)
func HandleHeadRequest(directory, torrentName, fileName string, w http.ResponseWriter, req *http.Request, torMgr *torrent.TorrentManager, log *zap.SugaredLogger) {
func HandleHeadRequest(directory, torrentName, fileName string, w http.ResponseWriter, req *http.Request, torMgr *torrent.TorrentManager, log *logutil.Logger) {
torrents, ok := torMgr.DirectoryMap.Get(directory)
if !ok {