hotfix non-webdav symlinker
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
# DecyphArr
|
# Decypharr
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**DecyphArr** is an implementation of QbitTorrent with **Multiple Debrid service support**, written in Go.
|
**Decypharr** is an implementation of QbitTorrent with **Multiple Debrid service support**, written in Go.
|
||||||
|
|
||||||
## What is DecyphArr?
|
## What is Decypharr?
|
||||||
|
|
||||||
DecyphArr combines the power of QBittorrent with popular Debrid services to enhance your media management. It provides a familiar interface for Sonarr, Radarr, and other \*Arr applications while leveraging the capabilities of Debrid providers.
|
Decypharr combines the power of QBittorrent with popular Debrid services to enhance your media management. It provides a familiar interface for Sonarr, Radarr, and other \*Arr applications while leveraging the capabilities of Debrid providers.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,57 @@ func (q *QBit) ProcessSymlink(torrent *Torrent) (string, error) {
|
|||||||
torrentFolder = utils.RemoveExtension(torrentFolder)
|
torrentFolder = utils.RemoveExtension(torrentFolder)
|
||||||
torrentRclonePath = rCloneBase // /mnt/rclone/magnets/ // Remove the filename since it's in the root folder
|
torrentRclonePath = rCloneBase // /mnt/rclone/magnets/ // Remove the filename since it's in the root folder
|
||||||
}
|
}
|
||||||
return q.createSymlinks(debridTorrent, torrentRclonePath, torrentFolder) // verify cos we're using external webdav
|
torrentSymlinkPath := filepath.Join(q.DownloadFolder, debridTorrent.Arr.Name, torrentFolder) // /mnt/symlinks/{category}/MyTVShow/
|
||||||
|
err = os.MkdirAll(torrentSymlinkPath, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to create directory: %s: %v", torrentSymlinkPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pending := make(map[string]debridTypes.File)
|
||||||
|
filePaths := make([]string, 0, len(files))
|
||||||
|
for _, file := range files {
|
||||||
|
pending[file.Path] = file
|
||||||
|
}
|
||||||
|
ticker := time.NewTicker(200 * time.Millisecond)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
timeout := time.After(30 * time.Minute) // Adjust timeout duration as needed
|
||||||
|
|
||||||
|
for len(pending) > 0 {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
for path, file := range pending {
|
||||||
|
fullFilePath := filepath.Join(torrentRclonePath, file.Path)
|
||||||
|
if _, err := os.Stat(fullFilePath); !os.IsNotExist(err) {
|
||||||
|
fileSymlinkPath := filepath.Join(torrentSymlinkPath, file.Name)
|
||||||
|
if err := os.Symlink(fullFilePath, fileSymlinkPath); err != nil && !os.IsExist(err) {
|
||||||
|
q.logger.Debug().Msgf("Failed to create symlink: %s: %v", fileSymlinkPath, err)
|
||||||
|
} else {
|
||||||
|
filePaths = append(filePaths, fileSymlinkPath)
|
||||||
|
delete(pending, path)
|
||||||
|
q.logger.Info().Msgf("File is ready: %s", file.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case <-timeout:
|
||||||
|
q.logger.Warn().Msgf("Timeout waiting for files, %d files still pending", len(pending))
|
||||||
|
return torrentSymlinkPath, fmt.Errorf("timeout waiting for files: %d files still pending", len(pending))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if q.SkipPreCache {
|
||||||
|
return torrentSymlinkPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
|
||||||
|
if err := q.preCacheFile(debridTorrent.Name, filePaths); err != nil {
|
||||||
|
q.logger.Error().Msgf("Failed to pre-cache file: %s", err)
|
||||||
|
} else {
|
||||||
|
q.logger.Trace().Msgf("Pre-cached %d files", len(filePaths))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return torrentSymlinkPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *QBit) createSymlinksWebdav(debridTorrent *debridTypes.Torrent, rclonePath, torrentFolder string) (string, error) {
|
func (q *QBit) createSymlinksWebdav(debridTorrent *debridTypes.Torrent, rclonePath, torrentFolder string) (string, error) {
|
||||||
@@ -232,70 +282,6 @@ func (q *QBit) createSymlinksWebdav(debridTorrent *debridTypes.Torrent, rclonePa
|
|||||||
return symlinkPath, nil
|
return symlinkPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *QBit) createSymlinks(debridTorrent *debridTypes.Torrent, rclonePath, torrentFolder string) (string, error) {
|
|
||||||
files := debridTorrent.Files
|
|
||||||
symlinkPath := filepath.Join(q.DownloadFolder, debridTorrent.Arr.Name, torrentFolder) // /mnt/symlinks/{category}/MyTVShow/
|
|
||||||
err := os.MkdirAll(symlinkPath, os.ModePerm)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to create directory: %s: %v", symlinkPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
remainingFiles := make(map[string]debridTypes.File)
|
|
||||||
for _, file := range files {
|
|
||||||
remainingFiles[file.Path] = file
|
|
||||||
}
|
|
||||||
|
|
||||||
ticker := time.NewTicker(100 * time.Millisecond)
|
|
||||||
defer ticker.Stop()
|
|
||||||
timeout := time.After(30 * time.Minute)
|
|
||||||
filePaths := make([]string, 0, len(files))
|
|
||||||
|
|
||||||
for len(remainingFiles) > 0 {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
entries, err := os.ReadDir(rclonePath)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check which files exist in this batch
|
|
||||||
for _, entry := range entries {
|
|
||||||
filename := entry.Name()
|
|
||||||
if file, exists := remainingFiles[filename]; exists {
|
|
||||||
fullFilePath := filepath.Join(rclonePath, filename)
|
|
||||||
fileSymlinkPath := filepath.Join(symlinkPath, file.Name)
|
|
||||||
|
|
||||||
if err := os.Symlink(fullFilePath, fileSymlinkPath); err != nil && !os.IsExist(err) {
|
|
||||||
q.logger.Debug().Msgf("Failed to create symlink: %s: %v", fileSymlinkPath, err)
|
|
||||||
} else {
|
|
||||||
filePaths = append(filePaths, fileSymlinkPath)
|
|
||||||
delete(remainingFiles, filename)
|
|
||||||
q.logger.Info().Msgf("File is ready: %s", file.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-timeout:
|
|
||||||
q.logger.Warn().Msgf("Timeout waiting for files, %d files still pending", len(remainingFiles))
|
|
||||||
return symlinkPath, fmt.Errorf("timeout waiting for files")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if q.SkipPreCache {
|
|
||||||
return symlinkPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
|
|
||||||
if err := q.preCacheFile(debridTorrent.Name, filePaths); err != nil {
|
|
||||||
q.logger.Error().Msgf("Failed to pre-cache file: %s", err)
|
|
||||||
} else {
|
|
||||||
q.logger.Trace().Msgf("Pre-cached %d files", len(filePaths))
|
|
||||||
}
|
|
||||||
}() // Pre-cache the files in the background
|
|
||||||
return symlinkPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *QBit) getTorrentPath(rclonePath string, debridTorrent *debridTypes.Torrent) (string, error) {
|
func (q *QBit) getTorrentPath(rclonePath string, debridTorrent *debridTypes.Torrent) (string, error) {
|
||||||
for {
|
for {
|
||||||
torrentPath, err := debridTorrent.GetMountFolder(rclonePath)
|
torrentPath, err := debridTorrent.GetMountFolder(rclonePath)
|
||||||
|
|||||||
Reference in New Issue
Block a user