diff --git a/go.mod b/go.mod index 70dc785..ea630cb 100644 --- a/go.mod +++ b/go.mod @@ -19,9 +19,11 @@ require ( ) require ( + github.com/gen2brain/go-unarr v0.2.3 // indirect github.com/looplab/fsm v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/nwaples/rardecode v1.1.3 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/vansante/go-ffprobe.v2 v2.1.1 // indirect ) diff --git a/go.sum b/go.sum index 3d2f116..72e64b0 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/gen2brain/go-unarr v0.2.3 h1:VwZg0P6Dc/8Uh51McjVhzUMg4wHwwbiyqjEFsFELc0c= +github.com/gen2brain/go-unarr v0.2.3/go.mod h1:hoHheVuf0KT8/hfvkEL7GMwj2h7fq0lF72NdyySdr3c= github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA= github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -19,6 +21,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8 h1:BhQQWYKJwXPtAhm12d4gQU4LKS9Yov22yOrDc2QA7ho= github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8/go.mod h1:ntWhh7pzdiiRKBMxUB5iG+Q2gmZBxGxpX1KyK6N8kX8= +github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= +github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c= github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM= github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo= diff --git a/internal/app.go b/internal/app.go index f02f26d..778567e 100644 --- a/internal/app.go +++ b/internal/app.go @@ -10,6 +10,7 @@ import ( "github.com/debridmediamanager/zurg/internal/config" "github.com/debridmediamanager/zurg/internal/handlers" + "github.com/debridmediamanager/zurg/internal/rar" "github.com/debridmediamanager/zurg/internal/torrent" "github.com/debridmediamanager/zurg/internal/universal" "github.com/debridmediamanager/zurg/internal/version" @@ -95,9 +96,12 @@ func MainApp(configPath string) { } defer workerPool.Release() + rarReader := rar.NewRarReader(downloadClient, log.Named("rar_reader")) + torrentMgr := torrent.NewTorrentManager( config, api, + rarReader, workerPool, log.Named("manager"), log.Named("repair"), diff --git a/internal/rar/contents.go b/internal/rar/contents.go new file mode 100644 index 0000000..2f6c5eb --- /dev/null +++ b/internal/rar/contents.go @@ -0,0 +1,69 @@ +package rar + +import ( + "fmt" + "net/http" + "strings" + + zurghttp "github.com/debridmediamanager/zurg/pkg/http" + "github.com/debridmediamanager/zurg/pkg/logutil" + "github.com/nwaples/rardecode" +) + +type RarReader struct { + client *zurghttp.HTTPClient + log *logutil.Logger +} + +func NewRarReader(client *zurghttp.HTTPClient, log *logutil.Logger) *RarReader { + return &RarReader{ + client: client, + log: log, + } +} + +// GetRARContents extracts the file names from a RAR archive. +func (r *RarReader) GetRARContents(downloadLink string) ([]string, error) { + dlReq, err := http.NewRequest(http.MethodGet, downloadLink, nil) + if err != nil { + return nil, err + } + + downloadResp, err := r.client.Do(dlReq) + if err != nil { + return nil, err + } + defer downloadResp.Body.Close() + + if downloadResp.StatusCode/100 != 2 { + return nil, fmt.Errorf("received a %s status code", downloadResp.Status) + } + + var fileList []string + + rarReader, err := rardecode.NewReader(downloadResp.Body, "") + if err != nil { + return nil, err + } + + for { + r.log.Debugf("Reading next file from RAR archive") + header, err := rarReader.Next() + if err != nil { + if strings.Contains(err.Error(), "unexpected EOF") { + break + } + return nil, err + } + + if header == nil { + break + } + + fileList = append(fileList, header.Name) + r.log.Debugf("Found file: %s", header.Name) + r.log.Debugf("File size: %d MB", header.PackedSize/1024/1024) + } + + return fileList, nil +} diff --git a/internal/torrent/manager.go b/internal/torrent/manager.go index 1a0c975..61b62b8 100644 --- a/internal/torrent/manager.go +++ b/internal/torrent/manager.go @@ -11,6 +11,7 @@ import ( "github.com/debridmediamanager/zurg/internal/config" "github.com/debridmediamanager/zurg/internal/fs" + "github.com/debridmediamanager/zurg/internal/rar" "github.com/debridmediamanager/zurg/pkg/logutil" "github.com/debridmediamanager/zurg/pkg/realdebrid" mapset "github.com/deckarep/golang-set/v2" @@ -28,6 +29,7 @@ type TorrentManager struct { Config config.ConfigInterface api *realdebrid.RealDebrid + rarReader *rar.RarReader workerPool *ants.Pool log *logutil.Logger repairLog *logutil.Logger @@ -58,12 +60,13 @@ type TorrentManager struct { // 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, workerPool *ants.Pool, log, repairLog *logutil.Logger) *TorrentManager { +func NewTorrentManager(cfg config.ConfigInterface, api *realdebrid.RealDebrid, rarReader *rar.RarReader, workerPool *ants.Pool, log, repairLog *logutil.Logger) *TorrentManager { t := &TorrentManager{ requiredVersion: "0.10.0", Config: cfg, api: api, + rarReader: rarReader, workerPool: workerPool, log: log, repairLog: repairLog, diff --git a/internal/torrent/repair.go b/internal/torrent/repair.go index 020cb61..fb01975 100644 --- a/internal/torrent/repair.go +++ b/internal/torrent/repair.go @@ -316,6 +316,12 @@ func (t *TorrentManager) assignLinks(torrent *Torrent) bool { if !assigned { // if not assigned and is a rar, likely it was rar'ed by RD if strings.HasSuffix(strings.ToLower(unrestrict.Filename), ".rar") { + // t.log.Debugf("Trying to get contents of rar file %s", unrestrict.Filename) + // contents, err := t.rarReader.GetRARContents(unrestrict.Download) + // if err != nil { + // t.repairLog.Warnf("Cannot get contents of rar file %s: %v", unrestrict.Filename, err) + // } + // t.log.Debugf("contents: %v", contents) rarCount++ } else { t.repairLog.Warnf("Cannot assign %s to any file in torrent %s", unrestrict.Filename, t.GetKey(torrent))