Skip to content

Commit 87bf8d0

Browse files
committed
Merge branch 'beta'
2 parents d313ed0 + 7f25599 commit 87bf8d0

File tree

11 files changed

+220
-105
lines changed

11 files changed

+220
-105
lines changed

pkg/debrid/debrid/cache.go

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/sirrobot01/decypharr/internal/logger"
2424
"github.com/sirrobot01/decypharr/internal/utils"
2525
"github.com/sirrobot01/decypharr/pkg/debrid/types"
26+
_ "time/tzdata"
2627
)
2728

2829
type WebDavFolderNaming string
@@ -109,9 +110,16 @@ type Cache struct {
109110

110111
func New(dc config.Debrid, client types.Client) *Cache {
111112
cfg := config.Get()
112-
cet, _ := time.LoadLocation("CET")
113-
cetSc, _ := gocron.NewScheduler(gocron.WithLocation(cet))
114-
scheduler, _ := gocron.NewScheduler(gocron.WithLocation(time.Local))
113+
cetSc, err := gocron.NewScheduler(gocron.WithLocation(time.UTC))
114+
if err != nil {
115+
// If we can't create a CET scheduler, fallback to local time
116+
cetSc, _ = gocron.NewScheduler(gocron.WithLocation(time.Local))
117+
}
118+
scheduler, err := gocron.NewScheduler(gocron.WithLocation(time.Local))
119+
if err != nil {
120+
// If we can't create a local scheduler, fallback to CET
121+
scheduler = cetSc
122+
}
115123

116124
autoExpiresLinksAfter, err := time.ParseDuration(dc.AutoExpireLinksAfter)
117125
if autoExpiresLinksAfter == 0 || err != nil {
@@ -307,10 +315,10 @@ func (c *Cache) load(ctx context.Context) (map[string]CachedTorrent, error) {
307315
}
308316

309317
isComplete := true
310-
if len(ct.Files) != 0 {
318+
if len(ct.GetFiles()) != 0 {
311319
// Check if all files are valid, if not, delete the file.json and remove from cache.
312-
fs := make(map[string]types.File, len(ct.Files))
313-
for _, f := range ct.Files {
320+
fs := make(map[string]types.File, len(ct.GetFiles()))
321+
for _, f := range ct.GetFiles() {
314322
if f.Link == "" {
315323
isComplete = false
316324
break
@@ -756,7 +764,7 @@ func (c *Cache) deleteTorrent(id string, removeFromDebrid bool) bool {
756764

757765
newFiles := map[string]types.File{}
758766
newId := ""
759-
for _, file := range t.Files {
767+
for _, file := range t.GetFiles() {
760768
if file.TorrentId != "" && file.TorrentId != id {
761769
if newId == "" && file.TorrentId != "" {
762770
newId = file.TorrentId
@@ -815,6 +823,36 @@ func (c *Cache) OnRemove(torrentId string) {
815823
}
816824
}
817825

826+
// RemoveFile removes a file from the torrent cache
827+
// TODO sends a re-insert that removes the file from debrid
828+
func (c *Cache) RemoveFile(torrentId string, filename string) error {
829+
c.logger.Debug().Str("torrent_id", torrentId).Msgf("Removing file %s", filename)
830+
torrent, ok := c.torrents.getByID(torrentId)
831+
if !ok {
832+
return fmt.Errorf("torrent %s not found", torrentId)
833+
}
834+
file, ok := torrent.GetFile(filename)
835+
if !ok {
836+
return fmt.Errorf("file %s not found in torrent %s", filename, torrentId)
837+
}
838+
file.Deleted = true
839+
torrent.Files[filename] = file
840+
841+
// If the torrent has no files left, delete it
842+
if len(torrent.GetFiles()) == 0 {
843+
c.logger.Debug().Msgf("Torrent %s has no files left, deleting it", torrentId)
844+
if err := c.DeleteTorrent(torrentId); err != nil {
845+
return fmt.Errorf("failed to delete torrent %s: %w", torrentId, err)
846+
}
847+
return nil
848+
}
849+
850+
c.setTorrent(torrent, func(torrent CachedTorrent) {
851+
c.listingDebouncer.Call(true)
852+
}) // Update the torrent in the cache
853+
return nil
854+
}
855+
818856
func (c *Cache) GetLogger() zerolog.Logger {
819857
return c.logger
820858
}

pkg/debrid/debrid/download_link.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,21 @@ func (c *Cache) fetchDownloadLink(torrentName, filename, fileLink string) (strin
103103
if ct == nil {
104104
return "", fmt.Errorf("torrent not found")
105105
}
106-
file := ct.Files[filename]
106+
file, ok := ct.GetFile(filename)
107+
if !ok {
108+
return "", fmt.Errorf("file %s not found in torrent %s", filename, torrentName)
109+
}
107110

108111
if file.Link == "" {
109112
// file link is empty, refresh the torrent to get restricted links
110113
ct = c.refreshTorrent(file.TorrentId) // Refresh the torrent from the debrid
111114
if ct == nil {
112115
return "", fmt.Errorf("failed to refresh torrent")
113116
} else {
114-
file = ct.Files[filename]
117+
file, ok = ct.GetFile(filename)
118+
if !ok {
119+
return "", fmt.Errorf("file %s not found in refreshed torrent %s", filename, torrentName)
120+
}
115121
}
116122
}
117123

@@ -123,7 +129,10 @@ func (c *Cache) fetchDownloadLink(torrentName, filename, fileLink string) (strin
123129
return "", fmt.Errorf("failed to reinsert torrent. %w", err)
124130
}
125131
ct = newCt
126-
file = ct.Files[filename]
132+
file, ok = ct.GetFile(filename)
133+
if !ok {
134+
return "", fmt.Errorf("file %s not found in reinserted torrent %s", filename, torrentName)
135+
}
127136
}
128137

129138
c.logger.Trace().Msgf("Getting download link for %s(%s)", filename, file.Link)
@@ -135,7 +144,10 @@ func (c *Cache) fetchDownloadLink(torrentName, filename, fileLink string) (strin
135144
return "", fmt.Errorf("failed to reinsert torrent: %w", err)
136145
}
137146
ct = newCt
138-
file = ct.Files[filename]
147+
file, ok = ct.GetFile(filename)
148+
if !ok {
149+
return "", fmt.Errorf("file %s not found in reinserted torrent %s", filename, torrentName)
150+
}
139151
// Retry getting the download link
140152
downloadLink, err = c.client.GetDownloadLink(ct.Torrent, &file)
141153
if err != nil {
@@ -165,7 +177,7 @@ func (c *Cache) GenerateDownloadLinks(t CachedTorrent) {
165177
c.logger.Error().Err(err).Str("torrent", t.Name).Msg("Failed to generate download links")
166178
return
167179
}
168-
for _, file := range t.Files {
180+
for _, file := range t.GetFiles() {
169181
if file.DownloadLink != nil {
170182
c.updateDownloadLink(file.DownloadLink)
171183
}

pkg/debrid/debrid/misc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func mergeFiles(torrents ...CachedTorrent) map[string]types.File {
1919
})
2020

2121
for _, torrent := range torrents {
22-
for _, file := range torrent.Files {
22+
for _, file := range torrent.GetFiles() {
2323
merged[file.Name] = file
2424
}
2525
}

pkg/debrid/debrid/repair.go

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,9 @@ func (c *Cache) markAsSuccessfullyReinserted(torrentId string) {
5959
}
6060
}
6161

62-
func (c *Cache) IsTorrentBroken(t *CachedTorrent, filenames []string) bool {
63-
// Check torrent files
64-
65-
isBroken := false
62+
func (c *Cache) GetBrokenFiles(t *CachedTorrent, filenames []string) []string {
6663
files := make(map[string]types.File)
64+
brokenFiles := make([]string, 0)
6765
if len(filenames) > 0 {
6866
for name, f := range t.Files {
6967
if utils.Contains(filenames, name) {
@@ -73,8 +71,6 @@ func (c *Cache) IsTorrentBroken(t *CachedTorrent, filenames []string) bool {
7371
} else {
7472
files = t.Files
7573
}
76-
77-
// Check empty links
7874
for _, f := range files {
7975
// Check if file is missing
8076
if f.Link == "" {
@@ -83,44 +79,43 @@ func (c *Cache) IsTorrentBroken(t *CachedTorrent, filenames []string) bool {
8379
t = newT
8480
} else {
8581
c.logger.Error().Str("torrentId", t.Torrent.Id).Msg("Failed to refresh torrent")
86-
return true
82+
return filenames // Return original filenames if refresh fails(torrent is somehow botched)
8783
}
8884
}
8985
}
9086

9187
if t.Torrent == nil {
9288
c.logger.Error().Str("torrentId", t.Torrent.Id).Msg("Failed to refresh torrent")
93-
return true
89+
return filenames // Return original filenames if refresh fails(torrent is somehow botched)
9490
}
9591

9692
files = t.Files
9793

9894
for _, f := range files {
9995
// Check if file link is still missing
10096
if f.Link == "" {
101-
isBroken = true
102-
break
97+
brokenFiles = append(brokenFiles, f.Name)
10398
} else {
10499
// Check if file.Link not in the downloadLink Cache
105100
if err := c.client.CheckLink(f.Link); err != nil {
106101
if errors.Is(err, request.HosterUnavailableError) {
107-
isBroken = true
108-
break
102+
brokenFiles = append(brokenFiles, f.Name)
109103
}
110104
}
111105
}
112106
}
107+
113108
// Try to reinsert the torrent if it's broken
114-
if isBroken && t.Torrent != nil {
109+
if len(brokenFiles) > 0 && t.Torrent != nil {
115110
// Check if the torrent is already in progress
116111
if _, err := c.reInsertTorrent(t); err != nil {
117112
c.logger.Error().Err(err).Str("torrentId", t.Torrent.Id).Msg("Failed to reinsert torrent")
118-
return true
113+
return brokenFiles // Return broken files if reinsert fails
119114
}
120-
return false
115+
return nil // Return nil if the torrent was successfully reinserted
121116
}
122117

123-
return isBroken
118+
return brokenFiles
124119
}
125120

126121
func (c *Cache) repairWorker(ctx context.Context) {
@@ -223,7 +218,7 @@ func (c *Cache) reInsertTorrent(ct *CachedTorrent) (*CachedTorrent, error) {
223218
if err != nil {
224219
addedOn = time.Now()
225220
}
226-
for _, f := range newTorrent.Files {
221+
for _, f := range newTorrent.GetFiles() {
227222
if f.Link == "" {
228223
c.markAsFailedToReinsert(oldID)
229224
return ct, fmt.Errorf("failed to reinsert torrent: empty link")

pkg/debrid/torbox/torbox.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ func (tb *Torbox) GetTorrent(torrentId string) (*types.Torrent, error) {
234234
Id: strconv.Itoa(f.Id),
235235
Name: fileName,
236236
Size: f.Size,
237-
Path: fileName,
237+
Path: f.Name,
238238
}
239239
t.Files[fileName] = file
240240
}

pkg/debrid/types/torrent.go

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Torrent struct {
2929
Seeders int `json:"seeders"`
3030
Links []string `json:"links"`
3131
MountPath string `json:"mount_path"`
32+
DeletedFiles []string `json:"deleted_files"`
3233

3334
Debrid string `json:"debrid"`
3435

@@ -75,6 +76,24 @@ func (t *Torrent) GetMountFolder(rClonePath string) (string, error) {
7576
return "", fmt.Errorf("no path found")
7677
}
7778

79+
func (t *Torrent) GetFile(filename string) (File, bool) {
80+
f, ok := t.Files[filename]
81+
if !ok {
82+
return File{}, false
83+
}
84+
return f, !f.Deleted
85+
}
86+
87+
func (t *Torrent) GetFiles() []File {
88+
files := make([]File, 0, len(t.Files))
89+
for _, f := range t.Files {
90+
if !f.Deleted {
91+
files = append(files, f)
92+
}
93+
}
94+
return files
95+
}
96+
7897
type File struct {
7998
TorrentId string `json:"torrent_id"`
8099
Id string `json:"id"`
@@ -85,6 +104,7 @@ type File struct {
85104
DownloadLink *DownloadLink `json:"-"`
86105
AccountId string `json:"account_id"`
87106
Generated time.Time `json:"generated"`
107+
Deleted bool `json:"deleted"`
88108
}
89109

90110
func (t *Torrent) Cleanup(remove bool) {
@@ -96,15 +116,6 @@ func (t *Torrent) Cleanup(remove bool) {
96116
}
97117
}
98118

99-
func (t *Torrent) GetFile(id string) *File {
100-
for _, f := range t.Files {
101-
if f.Id == id {
102-
return &f
103-
}
104-
}
105-
return nil
106-
}
107-
108119
type Account struct {
109120
ID string `json:"id"`
110121
Disabled bool `json:"disabled"`

pkg/qbit/downloader.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func (q *QBit) downloadFiles(torrent *Torrent, parent string) {
6868
var wg sync.WaitGroup
6969

7070
totalSize := int64(0)
71-
for _, file := range debridTorrent.Files {
71+
for _, file := range debridTorrent.GetFiles() {
7272
totalSize += file.Size
7373
}
7474
debridTorrent.Mu.Lock()
@@ -100,7 +100,7 @@ func (q *QBit) downloadFiles(torrent *Torrent, parent string) {
100100
},
101101
}
102102
errChan := make(chan error, len(debridTorrent.Files))
103-
for _, file := range debridTorrent.Files {
103+
for _, file := range debridTorrent.GetFiles() {
104104
if file.DownloadLink == nil {
105105
q.logger.Info().Msgf("No download link found for %s", file.Name)
106106
continue
@@ -170,15 +170,34 @@ func (q *QBit) ProcessSymlink(torrent *Torrent) (string, error) {
170170
return "", fmt.Errorf("failed to create directory: %s: %v", torrentSymlinkPath, err)
171171
}
172172

173+
realPaths := make(map[string]string)
174+
err = filepath.WalkDir(torrentRclonePath, func(path string, d os.DirEntry, err error) error {
175+
if err != nil {
176+
return nil
177+
}
178+
if !d.IsDir() {
179+
filename := d.Name()
180+
rel, _ := filepath.Rel(torrentRclonePath, path)
181+
realPaths[filename] = rel
182+
}
183+
return nil
184+
})
185+
if err != nil {
186+
q.logger.Warn().Msgf("Error while scanning rclone path: %v", err)
187+
}
188+
173189
pending := make(map[string]debridTypes.File)
174-
filePaths := make([]string, 0, len(files))
175190
for _, file := range files {
191+
if realRelPath, ok := realPaths[file.Name]; ok {
192+
file.Path = realRelPath
193+
}
176194
pending[file.Path] = file
177195
}
196+
178197
ticker := time.NewTicker(200 * time.Millisecond)
179198
defer ticker.Stop()
180-
181-
timeout := time.After(30 * time.Minute) // Adjust timeout duration as needed
199+
timeout := time.After(30 * time.Minute)
200+
filePaths := make([]string, 0, len(pending))
182201

183202
for len(pending) > 0 {
184203
select {
@@ -194,7 +213,6 @@ func (q *QBit) ProcessSymlink(torrent *Torrent) (string, error) {
194213
delete(pending, path)
195214
q.logger.Info().Msgf("File is ready: %s", file.Name)
196215
}
197-
198216
}
199217
}
200218
case <-timeout:

0 commit comments

Comments
 (0)