Add retain_folder_name_extension option

This commit is contained in:
Ben Sarmiento
2023-11-07 17:20:54 +01:00
parent d5746fcf5a
commit c2bf627413
10 changed files with 41 additions and 74 deletions

View File

@@ -11,6 +11,7 @@ enable_repair: true # BEWARE! THERE CAN ONLY BE 1 INSTANCE OF ZURG THAT SHOULD R
on_library_update: | on_library_update: |
echo "hook" echo "hook"
network_buffer_size: 32768 # 32KB network_buffer_size: 32768 # 32KB
retain_folder_name_extension: false # if true, the folder name will contain the file extension when it is a torrent for a single file
# List of directory definitions and their filtering rules # List of directory definitions and their filtering rules
directories: directories:

View File

@@ -22,6 +22,7 @@ type ConfigInterface interface {
GetOnLibraryUpdate() string GetOnLibraryUpdate() string
GetNetworkBufferSize() int GetNetworkBufferSize() int
GetMountPoint() string GetMountPoint() string
EnableRetainFolderNameExtension() bool
} }
func LoadZurgConfig(filename string) (ConfigInterface, error) { func LoadZurgConfig(filename string) (ConfigInterface, error) {

View File

@@ -1,17 +1,18 @@
package config package config
type ZurgConfig struct { type ZurgConfig struct {
Version string `yaml:"zurg"` Version string `yaml:"zurg"`
Token string `yaml:"token"` Token string `yaml:"token"`
Host string `yaml:"host"` Host string `yaml:"host"`
Port string `yaml:"port"` Port string `yaml:"port"`
NumOfWorkers int `yaml:"concurrent_workers"` NumOfWorkers int `yaml:"concurrent_workers"`
RefreshEverySeconds int `yaml:"check_for_changes_every_secs"` RefreshEverySeconds int `yaml:"check_for_changes_every_secs"`
CacheTimeHours int `yaml:"info_cache_time_hours"` CacheTimeHours int `yaml:"info_cache_time_hours"`
CanRepair bool `yaml:"enable_repair"` CanRepair bool `yaml:"enable_repair"`
OnLibraryUpdate string `yaml:"on_library_update"` OnLibraryUpdate string `yaml:"on_library_update"`
NetworkBufferSize int `yaml:"network_buffer_size"` NetworkBufferSize int `yaml:"network_buffer_size"`
MountPoint string `yaml:"mount_point"` MountPoint string `yaml:"mount_point"`
RetainFolderNameExtension bool `yaml:"retain_folder_name_extension"`
} }
func (z *ZurgConfig) GetToken() string { func (z *ZurgConfig) GetToken() string {
@@ -68,3 +69,7 @@ func (z *ZurgConfig) GetNetworkBufferSize() int {
func (z *ZurgConfig) GetMountPoint() string { func (z *ZurgConfig) GetMountPoint() string {
return z.MountPoint return z.MountPoint
} }
func (z *ZurgConfig) EnableRetainFolderNameExtension() bool {
return z.RetainFolderNameExtension
}

View File

@@ -49,14 +49,13 @@ func createSingleTorrentResponse(basePath string, torrents []torrent.Torrent) (*
for _, torrent := range torrents { for _, torrent := range torrents {
for _, file := range torrent.SelectedFiles { for _, file := range torrent.SelectedFiles {
if file.Link == "" { if file.Link == "" {
// TODO: fix the file?
// log.Println("File has no link, skipping (repairing links take time)", file.Path) // log.Println("File has no link, skipping (repairing links take time)", file.Path)
continue continue
} }
filename := filepath.Base(file.Path) filename := filepath.Base(file.Path)
if finalName[filename] { if finalName[filename] {
// fragment := davextra.GetLinkFragment(file.Link)
// filename = davextra.InsertLinkFragment(filename, fragment)
continue continue
} }
finalName[filename] = true finalName[filename] = true

View File

@@ -40,14 +40,13 @@ func createSingleTorrentResponse(basePath string, torrents []torrent.Torrent) (s
for _, torrent := range torrents { for _, torrent := range torrents {
for _, file := range torrent.SelectedFiles { for _, file := range torrent.SelectedFiles {
if file.Link == "" { if file.Link == "" {
// TODO: fix the file?
// log.Println("File has no link, skipping", file.Path) // log.Println("File has no link, skipping", file.Path)
continue continue
} }
filename := filepath.Base(file.Path) filename := filepath.Base(file.Path)
if finalName[filename] { if finalName[filename] {
// fragment := davextra.GetLinkFragment(file.Link)
// filename = davextra.InsertLinkFragment(filename, fragment)
continue continue
} }
finalName[filename] = true finalName[filename] = true

View File

@@ -35,7 +35,7 @@ type TorrentManager struct {
// and store them in-memory; it is called only once at startup // and store them in-memory; it is called only once at startup
func NewTorrentManager(config config.ConfigInterface, cache *expirable.LRU[string, string]) *TorrentManager { func NewTorrentManager(config config.ConfigInterface, cache *expirable.LRU[string, string]) *TorrentManager {
t := &TorrentManager{ t := &TorrentManager{
requiredVersion: "4.11.2023", requiredVersion: fmt.Sprintf("4.11.2023 - retain:%v", config.EnableRetainFolderNameExtension()),
config: config, config: config,
cache: cache, cache: cache,
workerPool: make(chan bool, config.GetNumOfWorkers()), workerPool: make(chan bool, config.GetNumOfWorkers()),
@@ -256,7 +256,7 @@ func (t *TorrentManager) addMoreInfo(torrent *Torrent) {
// see if api data and file data still match // see if api data and file data still match
// then it means data is still usable // then it means data is still usable
if len(torrentFromFile.Links) == len(torrent.Links) { if len(torrentFromFile.Links) == len(torrent.Links) {
torrent.Name = getName(torrentFromFile) torrent.Name = t.getName(torrentFromFile)
torrent.ForRepair = torrentFromFile.ForRepair torrent.ForRepair = torrentFromFile.ForRepair
torrent.SelectedFiles = torrentFromFile.SelectedFiles[:] torrent.SelectedFiles = torrentFromFile.SelectedFiles[:]
return return
@@ -323,7 +323,7 @@ func (t *TorrentManager) addMoreInfo(torrent *Torrent) {
} }
// update file cache // update file cache
torrent.OriginalName = info.OriginalName torrent.OriginalName = info.OriginalName
torrent.Name = getName(torrent) torrent.Name = t.getName(torrent)
if len(selectedFiles) > 0 { if len(selectedFiles) > 0 {
// update the torrent with more data! // update the torrent with more data!
torrent.SelectedFiles = selectedFiles torrent.SelectedFiles = selectedFiles
@@ -332,16 +332,17 @@ func (t *TorrentManager) addMoreInfo(torrent *Torrent) {
} }
} }
func getName(torrent *Torrent) string { func (t *TorrentManager) getName(torrent *Torrent) string {
ret := "" // drop the extension from the name
if torrent.OriginalName != "" { t.log.Debugf("Original name: %s", torrent.OriginalName)
ret = torrent.OriginalName t.log.Debugf("Name: %s", torrent.Name)
if t.config.EnableRetainFolderNameExtension() && strings.Contains(torrent.Name, torrent.OriginalName) {
return torrent.Name
} else { } else {
ret = torrent.Name ret := strings.TrimSuffix(torrent.OriginalName, ".mp4")
ret = strings.TrimSuffix(ret, ".mkv")
return ret
} }
ret = strings.TrimSuffix(ret, ".mkv")
ret = strings.TrimSuffix(ret, ".mp4")
return ret
} }
// mapToDirectories maps torrents to directories // mapToDirectories maps torrents to directories

View File

@@ -11,7 +11,6 @@ import (
"github.com/debridmediamanager.com/zurg/internal/dav" "github.com/debridmediamanager.com/zurg/internal/dav"
intHttp "github.com/debridmediamanager.com/zurg/internal/http" intHttp "github.com/debridmediamanager.com/zurg/internal/http"
"github.com/debridmediamanager.com/zurg/internal/torrent" "github.com/debridmediamanager.com/zurg/internal/torrent"
"github.com/debridmediamanager.com/zurg/pkg/davextra"
"github.com/debridmediamanager.com/zurg/pkg/logutil" "github.com/debridmediamanager.com/zurg/pkg/logutil"
"github.com/debridmediamanager.com/zurg/pkg/realdebrid" "github.com/debridmediamanager.com/zurg/pkg/realdebrid"
"github.com/hashicorp/golang-lru/v2/expirable" "github.com/hashicorp/golang-lru/v2/expirable"
@@ -58,8 +57,7 @@ func HandleGetRequest(w http.ResponseWriter, r *http.Request, t *torrent.Torrent
return return
} }
filenameV2, linkFragment := davextra.ExtractLinkFragment(filename) torrent, file := getFile(torrents, filename)
torrent, file := getFile(torrents, filenameV2, linkFragment)
if file == nil { if file == nil {
log.Errorf("Cannot find file from path %s", requestPath) log.Errorf("Cannot find file from path %s", requestPath)
http.Error(w, "File not found", http.StatusNotFound) http.Error(w, "File not found", http.StatusNotFound)
@@ -79,20 +77,20 @@ func HandleGetRequest(w http.ResponseWriter, r *http.Request, t *torrent.Torrent
resp := realdebrid.RetryUntilOk(unrestrictFn) resp := realdebrid.RetryUntilOk(unrestrictFn)
if resp == nil { if resp == nil {
if !file.Unavailable { if !file.Unavailable {
log.Errorf("Cannot unrestrict file %s %s", filenameV2, link) log.Errorf("Cannot unrestrict file %s %s", filename, link)
t.HideTheFile(torrent, file) t.HideTheFile(torrent, file)
} }
streamErrorVideo("https://www.youtube.com/watch?v=gea_FJrtFVA", w, r, c, log) streamErrorVideo("https://www.youtube.com/watch?v=gea_FJrtFVA", w, r, c, log)
return return
} else if resp.Filename != filenameV2 { } else if resp.Filename != filename {
actualExt := filepath.Ext(resp.Filename) actualExt := filepath.Ext(resp.Filename)
expectedExt := filepath.Ext(filenameV2) expectedExt := filepath.Ext(filename)
if actualExt != expectedExt && resp.Streamable != 1 { if actualExt != expectedExt && resp.Streamable != 1 {
log.Errorf("File extension mismatch: %s and %s", filenameV2, resp.Filename) log.Errorf("File extension mismatch: %s and %s", filename, resp.Filename)
streamErrorVideo("https://www.youtube.com/watch?v=t9VgOriBHwE", w, r, c, log) streamErrorVideo("https://www.youtube.com/watch?v=t9VgOriBHwE", w, r, c, log)
return return
} else { } else {
log.Errorf("Filename mismatch: %s and %s", filenameV2, resp.Filename) log.Errorf("Filename mismatch: %s and %s", filename, resp.Filename)
} }
} }
cache.Add(requestPath, resp.Download) cache.Add(requestPath, resp.Download)

View File

@@ -9,7 +9,6 @@ import (
"github.com/debridmediamanager.com/zurg/internal/config" "github.com/debridmediamanager.com/zurg/internal/config"
"github.com/debridmediamanager.com/zurg/internal/torrent" "github.com/debridmediamanager.com/zurg/internal/torrent"
"github.com/debridmediamanager.com/zurg/pkg/davextra"
"github.com/debridmediamanager.com/zurg/pkg/logutil" "github.com/debridmediamanager.com/zurg/pkg/logutil"
"github.com/hashicorp/golang-lru/v2/expirable" "github.com/hashicorp/golang-lru/v2/expirable"
) )
@@ -53,8 +52,7 @@ func HandleHeadRequest(w http.ResponseWriter, r *http.Request, t *torrent.Torren
return return
} }
filenameV2, linkFragment := davextra.ExtractLinkFragment(filename) _, file := getFile(torrents, filename)
_, file := getFile(torrents, filenameV2, linkFragment)
if file == nil { if file == nil {
log.Errorf("Cannot find file from path %s", requestPath) log.Errorf("Cannot find file from path %s", requestPath)
http.Error(w, "Cannot find file", http.StatusNotFound) http.Error(w, "Cannot find file", http.StatusNotFound)

View File

@@ -2,17 +2,16 @@ package universal
import ( import (
"path/filepath" "path/filepath"
"strings"
"github.com/debridmediamanager.com/zurg/internal/torrent" "github.com/debridmediamanager.com/zurg/internal/torrent"
) )
// getFile finds a link by a fragment, it might be wrong // getFile finds a link by a fragment, it might be wrong
func getFile(torrents []torrent.Torrent, filename, fragment string) (*torrent.Torrent, *torrent.File) { func getFile(torrents []torrent.Torrent, filename string) (*torrent.Torrent, *torrent.File) {
for t := range torrents { for t := range torrents {
for f, file := range torrents[t].SelectedFiles { for f, file := range torrents[t].SelectedFiles {
fname := filepath.Base(file.Path) fname := filepath.Base(file.Path)
if filename == fname && strings.Contains(file.Link, fragment) { if filename == fname {
return &torrents[t], &torrents[t].SelectedFiles[f] return &torrents[t], &torrents[t].SelectedFiles[f]
} }
} }

View File

@@ -1,11 +1,7 @@
package davextra package davextra
import ( import (
"fmt"
"net/url"
"path/filepath"
"regexp" "regexp"
"strings"
) )
// GetLinkFragment returns the longest alphanumeric string from a link // GetLinkFragment returns the longest alphanumeric string from a link
@@ -20,33 +16,3 @@ func GetLinkFragment(link string) string {
} }
return longestMatch[:4] return longestMatch[:4]
} }
// InsertLinkFragment inserts the link ID into a filename
// returns the new filename
func InsertLinkFragment(filename, dupeID string) string {
ext := filepath.Ext(filename)
name := strings.TrimSuffix(filename, ext)
return fmt.Sprintf("%s DMM%s%s", name, dupeID, ext)
}
// ExtractLinkFragment extracts the link ID from a filename
// returns the original filename and the link ID
func ExtractLinkFragment(filename string) (string, string) {
filenameV2, err := url.PathUnescape(filename)
if err != nil {
filenameV2 = filename
}
ext := filepath.Ext(filenameV2)
name := strings.TrimSuffix(filenameV2, ext)
r := regexp.MustCompile(`\sDMM(\w+)`)
matches := r.FindStringSubmatch(name)
if len(matches) < 2 {
// No ID found
return filenameV2, ""
}
// Remove ID from filename
originalName := strings.Replace(name, matches[0], "", 1)
return originalName + ext, matches[1]
}