From d0ecaa0752e6477379828167c991e430ddcdaa0c Mon Sep 17 00:00:00 2001 From: Ben Sarmiento Date: Tue, 12 Dec 2023 02:00:25 +0100 Subject: [PATCH] Add infuse route --- internal/dav/infuse.go | 83 +++++++++++++++++++++++++++++++++++++++ internal/router/router.go | 55 ++++++++++++++++++++++---- 2 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 internal/dav/infuse.go diff --git a/internal/dav/infuse.go b/internal/dav/infuse.go new file mode 100644 index 0000000..cfdfc7d --- /dev/null +++ b/internal/dav/infuse.go @@ -0,0 +1,83 @@ +package dav + +import ( + "bytes" + "fmt" + "sort" + "strings" + + "github.com/debridmediamanager/zurg/internal/config" + "github.com/debridmediamanager/zurg/internal/torrent" + "github.com/debridmediamanager/zurg/pkg/dav" + "github.com/debridmediamanager/zurg/pkg/logutil" +) + +func HandleInfuseListDirectories(torMgr *torrent.TorrentManager) ([]byte, error) { + var buf bytes.Buffer + buf.WriteString("") + directories := torMgr.DirectoryMap.Keys() + sort.Strings(directories) + for _, directory := range directories { + if strings.HasPrefix(directory, "int__") { + continue + } + buf.WriteString(dav.BaseDirectory(directory, "")) + } + buf.WriteString("") + return buf.Bytes(), nil +} + +func HandleInfuseListTorrents(directory string, torMgr *torrent.TorrentManager, log *logutil.Logger) ([]byte, error) { + torrents, ok := torMgr.DirectoryMap.Get(directory) + if !ok { + return nil, fmt.Errorf("cannot find directory %s", directory) + } + + var buf bytes.Buffer + buf.WriteString("") + torrentNames := torrents.Keys() + sort.Strings(torrentNames) + for _, torrentName := range torrentNames { + tor, ok := torrents.Get(torrentName) + if !ok || tor.AllInProgress() { + continue + } + buf.WriteString(dav.BaseDirectory(tor.AccessKey, tor.LatestAdded)) + } + buf.WriteString("") + return buf.Bytes(), nil +} + +func HandleInfuseListFiles(directory, torrentName string, torMgr *torrent.TorrentManager, log *logutil.Logger) ([]byte, error) { + torrents, ok := torMgr.DirectoryMap.Get(directory) + if !ok { + return nil, fmt.Errorf("cannot find directory %s", directory) + } + tor, ok := torrents.Get(torrentName) + if !ok { + return nil, fmt.Errorf("cannot find torrent %s", torrentName) + } + + dirCfg := torMgr.Config.(*config.ZurgConfigV1).GetDirectoryConfig(directory) + biggestFileSize := int64(0) + if dirCfg.OnlyShowTheBiggestFile { + biggestFileSize = tor.ComputeBiggestFileSize() + } + + var buf bytes.Buffer + buf.WriteString("") + filenames := tor.SelectedFiles.Keys() + sort.Strings(filenames) + for _, filename := range filenames { + file, ok := tor.SelectedFiles.Get(filename) + if !ok || !strings.HasPrefix(file.Link, "http") { + continue + } + if dirCfg.OnlyShowTheBiggestFile && file.Bytes < biggestFileSize { + continue + } + buf.WriteString(dav.File(filename, file.Bytes, file.Ended)) + } + buf.WriteString("") + return buf.Bytes(), nil +} diff --git a/internal/router/router.go b/internal/router/router.go index 24e8c9c..3c02173 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -42,13 +42,13 @@ func ApplyRouteTable(router *httprouter.Router, getfile *universal.GetFile, torM // dav router router.GET("/dav/:directory/:torrent/:file", zr.universalDownloadFileHandler) - router.GET("/dav/:directory/:torrent/", zr.propfindTorrentHandler) - router.GET("/dav/:directory/", zr.propfindDirectoryHandler) - router.GET("/dav/", zr.propfindRootHandler) - // PROPFIND routes router.Handle("PROPFIND", "/dav/:directory/:torrent/", zr.propfindTorrentHandler) router.Handle("PROPFIND", "/dav/:directory/", zr.propfindDirectoryHandler) router.Handle("PROPFIND", "/dav/", zr.propfindRootHandler) + // extras + router.GET("/dav/:directory/:torrent/", zr.propfindTorrentHandler) + router.GET("/dav/:directory/", zr.propfindDirectoryHandler) + router.GET("/dav/", zr.propfindRootHandler) // DELETE routes router.DELETE("/dav/:directory/:torrent/:file", zr.deleteFileHandler) router.DELETE("/dav/:directory/:torrent/", zr.deleteTorrentHandler) @@ -56,9 +56,14 @@ func ApplyRouteTable(router *httprouter.Router, getfile *universal.GetFile, torM router.Handle("PROPFIND", "/dav/:directory/:torrent/:file", zr.propfindFileHandler) router.Handle("MKCOL", "/dav/:directory/:torrent/", zr.mkcolTorrentHandler) router.Handle("MOVE", "/dav/:directory/:torrent/:file", zr.moveFileHandler) - // MOVE routes router.Handle("MOVE", "/dav/:directory/:torrent/", zr.moveTorrentHandler) + // infuse routes + router.GET("/infuse/:directory/:torrent/:file", zr.universalDownloadFileHandler) + router.Handle("PROPFIND", "/infuse/:directory/:torrent/", zr.propfindInfuseTorrentHandler) + router.Handle("PROPFIND", "/infuse/:directory/", zr.propfindInfuseDirectoryHandler) + router.Handle("PROPFIND", "/infuse/", zr.propfindInfuseRootHandler) + // Global OPTIONS route router.GlobalOPTIONS = http.HandlerFunc(zr.globalOptionsHandler) @@ -70,8 +75,8 @@ func ApplyRouteTable(router *httprouter.Router, getfile *universal.GetFile, torM router.GET("/logs/", zr.logsHandler) router.MethodNotAllowed = http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - zr.log.Debugf("Method Not Allowed: %s %s %v", req.Method, req.URL, req.Header) - http.Error(resp, "Method Not Allowed", http.StatusMethodNotAllowed) + zr.log.Debugf("Method not allowed: %s %s %v", req.Method, req.URL, req.Header) + http.Error(resp, "Method not allowed", http.StatusMethodNotAllowed) }) } @@ -127,6 +132,42 @@ func (zr *ZurgRouter) propfindFileHandler(resp http.ResponseWriter, req *http.Re resp.Write(out) } +func (zr *ZurgRouter) propfindInfuseTorrentHandler(resp http.ResponseWriter, req *http.Request, params httprouter.Params) { + directory := params.ByName("directory") + torrentName := params.ByName("torrent") + out, err := dav.HandleInfuseListFiles(directory, torrentName, zr.torMgr, zr.log) + if err != nil { + http.Error(resp, "Not Found", http.StatusNotFound) + return + } + resp.Header().Set("Content-Type", "text/xml; charset=\"utf-8\"") + resp.WriteHeader(http.StatusOK) + resp.Write(out) +} + +func (zr *ZurgRouter) propfindInfuseDirectoryHandler(resp http.ResponseWriter, req *http.Request, params httprouter.Params) { + directory := params.ByName("directory") + out, err := dav.HandleInfuseListTorrents(directory, zr.torMgr, zr.log) + if err != nil { + http.Error(resp, "Not Found", http.StatusNotFound) + return + } + resp.Header().Set("Content-Type", "text/xml; charset=\"utf-8\"") + resp.WriteHeader(http.StatusOK) + resp.Write(out) +} + +func (zr *ZurgRouter) propfindInfuseRootHandler(resp http.ResponseWriter, req *http.Request, params httprouter.Params) { + out, err := dav.HandleInfuseListDirectories(zr.torMgr) + if err != nil { + http.Error(resp, "Not Found", http.StatusNotFound) + return + } + resp.Header().Set("Content-Type", "text/xml; charset=\"utf-8\"") + resp.WriteHeader(http.StatusOK) + resp.Write(out) +} + func (zr *ZurgRouter) propfindTorrentHandler(resp http.ResponseWriter, req *http.Request, params httprouter.Params) { directory := params.ByName("directory") torrentName := params.ByName("torrent")