diff --git a/internal/dav/vidhub.go b/internal/dav/vidhub.go new file mode 100644 index 0000000..fad11a8 --- /dev/null +++ b/internal/dav/vidhub.go @@ -0,0 +1,128 @@ +package dav + +import ( + "bytes" + "fmt" + "path/filepath" + "sort" + "strings" + + "github.com/debridmediamanager/zurg/internal/config" + "github.com/debridmediamanager/zurg/internal/torrent" + "github.com/debridmediamanager/zurg/internal/version" + "github.com/debridmediamanager/zurg/pkg/dav" +) + +func ServeRootDirectoryForVidHub(torMgr *torrent.TorrentManager) ([]byte, error) { + var buf bytes.Buffer + buf.WriteString("") + prefixPath := addSlash("") + buf.WriteString(dav.VidHubDirectory(prefixPath, "")) + directories := torMgr.DirectoryMap.Keys() + sort.Strings(directories) + for _, directory := range directories { + if strings.HasPrefix(directory, "int__") { + continue + } + buf.WriteString(dav.VidHubDirectory(prefixPath+directory, "")) + } + buf.WriteString(dav.VidHubDirectory(prefixPath+config.DOWNLOADS, "")) + _, size := version.GetFile() + buf.WriteString(dav.VidHubFile(prefixPath+version.FILE, size, "")) + buf.WriteString("") + return buf.Bytes(), nil +} + +func ServeTorrentsListForVidHub(directory string, torMgr *torrent.TorrentManager) ([]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("") + prefixPath := addSlash(directory) + buf.WriteString(dav.VidHubDirectory(prefixPath, "")) + torrentNames := torrents.Keys() + sort.Strings(torrentNames) + for _, torrentName := range torrentNames { + tor, ok := torrents.Get(torrentName) + if !ok { + continue + } + buf.WriteString(dav.VidHubDirectory(prefixPath+torMgr.GetKey(tor), tor.Added)) + } + buf.WriteString("") + return buf.Bytes(), nil +} + +func ServeFilesListForVidHub(directory, torrentName string, torMgr *torrent.TorrentManager, shouldHideBrokenTorrents bool) ([]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("") + prefixPath := addSlash(filepath.Join(directory, torMgr.GetKey(tor))) + buf.WriteString(dav.VidHubDirectory(prefixPath, tor.Added)) + filenames := tor.SelectedFiles.Keys() + sort.Strings(filenames) + for _, filename := range filenames { + file, _ := tor.SelectedFiles.Get(filename) + if file.State.Is("deleted_file") { + continue + } + if file.State.Is("broken_file") && shouldHideBrokenTorrents { + continue + } + if dirCfg.OnlyShowTheBiggestFile && file.Bytes < biggestFileSize { + continue + } + if dirCfg.OnlyShowFilesWithSizeLte > 0 && file.Bytes > dirCfg.OnlyShowFilesWithSizeLte { + continue + } + if dirCfg.OnlyShowFilesWithSizeGte > 0 && file.Bytes < dirCfg.OnlyShowFilesWithSizeGte { + continue + } + buf.WriteString(dav.VidHubFile(prefixPath+filename, file.Bytes, file.Ended)) + } + buf.WriteString("") + return buf.Bytes(), nil +} + +func ServeDownloadsListForVidHub(torMgr *torrent.TorrentManager) ([]byte, error) { + var buf bytes.Buffer + buf.WriteString("") + prefixPath := addSlash(config.DOWNLOADS) + buf.WriteString(dav.VidHubDirectory(prefixPath, "")) + filenames := torMgr.DownloadMap.Keys() + sort.Strings(filenames) + for _, filename := range filenames { + download, ok := torMgr.DownloadMap.Get(filename) + if !ok { + continue + } + buf.WriteString(dav.VidHubFile(prefixPath+filename, download.Filesize, download.Generated)) + } + buf.WriteString("") + return buf.Bytes(), nil +} + +func addSlash(input string) string { + p := filepath.Join("/", input) + if p == "/" || strings.HasSuffix(p, "/") { + return p + } + return p + "/" +} diff --git a/pkg/dav/response.go b/pkg/dav/response.go index 283b257..164a138 100644 --- a/pkg/dav/response.go +++ b/pkg/dav/response.go @@ -3,12 +3,13 @@ package dav import ( "fmt" "path/filepath" + "strings" ) // optimized versions, no more marshalling func BaseDirectory(path, added string) string { - return fmt.Sprintf("/%s%sHTTP/1.1 200 OK", customPathEscape(path), added) + return fmt.Sprintf("%s%sHTTP/1.1 200 OK", customPathEscape(path), added) } func Directory(path, added string) string { @@ -16,7 +17,22 @@ func Directory(path, added string) string { return fmt.Sprintf("%s%sHTTP/1.1 200 OK", customPathEscape(path), added) } +func BaseFile(path string, fileSize int64, added string) string { + return fmt.Sprintf("%s%d%sHTTP/1.1 200 OK", customPathEscape(path), fileSize, added) +} + func File(path string, fileSize int64, added string) string { path = filepath.Base(path) return fmt.Sprintf("%s%d%sHTTP/1.1 200 OK", customPathEscape(path), fileSize, added) } + +func VidHubDirectory(path, added string) string { + if !strings.HasSuffix(path, "/") { + path += "/" + } + return fmt.Sprintf("%s%sHTTP/1.1 200 OK", customPathEscape2(path), added) +} + +func VidHubFile(path string, fileSize int64, added string) string { + return fmt.Sprintf("%s%d%sHTTP/1.1 200 OK", customPathEscape2(path), fileSize, added) +} diff --git a/pkg/dav/util.go b/pkg/dav/util.go index 9064316..d1e0756 100644 --- a/pkg/dav/util.go +++ b/pkg/dav/util.go @@ -23,3 +23,13 @@ func customPathEscape(input string) string { escapedPath = strings.ReplaceAll(escapedPath, "@", "%40") return escapedPath } + +func customPathEscape2(input string) string { + // Convert any XML-escaped sequences back to URL-escaped sequences + input = strings.ReplaceAll(input, "$", "%24") + input = strings.ReplaceAll(input, "&", "%26") + input = strings.ReplaceAll(input, "+", "%2B") + input = strings.ReplaceAll(input, ":", "%3A") + input = strings.ReplaceAll(input, "@", "%40") + return input +}