From cfb0f12fff1458153db212bc1012da57334959a8 Mon Sep 17 00:00:00 2001 From: Ben Sarmiento Date: Sun, 7 Jan 2024 18:24:12 +0100 Subject: [PATCH] mark as unplayable and availability check --- internal/torrent/repair.go | 31 +++++++++++++++++++++++++------ pkg/realdebrid/api.go | 32 ++++++++++++++++++++++++++++++++ pkg/realdebrid/types.go | 14 ++++++++++++++ 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/internal/torrent/repair.go b/internal/torrent/repair.go index b8affe0..eab9f2a 100644 --- a/internal/torrent/repair.go +++ b/internal/torrent/repair.go @@ -22,11 +22,24 @@ func (t *TorrentManager) RepairAll() { func (t *TorrentManager) repairAll() { allTorrents, _ := t.DirectoryMap.Get(INT_ALL) + + hashes := make([]string, 0) + allTorrents.IterCb(func(_ string, torrent *Torrent) { + if torrent.AnyInProgress() || torrent.Unfixable { + return + } + hashes = append(hashes, torrent.Hash) + }) + var toRepair []*Torrent allTorrents.IterCb(func(_ string, torrent *Torrent) { if torrent.AnyInProgress() || torrent.Unfixable { return } + + // check 1: for cached status + + // check 2: for broken files hasBrokenFiles := false torrent.SelectedFiles.IterCb(func(_ string, file *File) { if file.Link == "repair" || file.Link == "" { @@ -135,11 +148,7 @@ func (t *TorrentManager) repair(torrent *Torrent) { } torrent.SelectedFiles.Set(unassigned.Filename, newFile) } - t.DirectoryMap.IterCb(func(directory string, torrents cmap.ConcurrentMap[string, *Torrent]) { - torrents.Remove(torrent.AccessKey) - }) - torrents, _ := t.DirectoryMap.Get(config.UNPLAYABLE_TORRENTS) - torrents.Set(torrent.AccessKey, torrent) + t.markAsUnplayable(torrent) } return } @@ -177,7 +186,7 @@ func (t *TorrentManager) repair(torrent *Torrent) { t.log.Infof("Successfully downloaded torrent %s to repair it", torrent.AccessKey) } else { t.log.Warnf("Failed to repair torrent %s", torrent.AccessKey) - torrent.Unfixable = true + t.markAsUnplayable(torrent) } } else { t.log.Warnf("Torrent %s has no broken files to repair", torrent.AccessKey) @@ -298,3 +307,13 @@ func (t *TorrentManager) canCapacityHandle() bool { retryCount++ } } + +func (t *TorrentManager) markAsUnplayable(torrent *Torrent) { + t.log.Warnf("Marking torrent %s as unplayable", torrent.AccessKey) + torrent.Unfixable = true + t.DirectoryMap.IterCb(func(directory string, torrents cmap.ConcurrentMap[string, *Torrent]) { + torrents.Remove(torrent.AccessKey) + }) + torrents, _ := t.DirectoryMap.Get(config.UNPLAYABLE_TORRENTS) + torrents.Set(torrent.AccessKey, torrent) +} diff --git a/pkg/realdebrid/api.go b/pkg/realdebrid/api.go index b84a36c..49ae7a5 100644 --- a/pkg/realdebrid/api.go +++ b/pkg/realdebrid/api.go @@ -390,3 +390,35 @@ func (rd *RealDebrid) GetUserInformation() (*User, error) { return &user, nil } + +// AvailabilityCheck checks the instant availability of torrents +func (rd *RealDebrid) AvailabilityCheck(hashes []string) (AvailabilityResponse, error) { + if len(hashes) == 0 { + return nil, fmt.Errorf("no hashes provided") + } + + baseURL := "https://api.real-debrid.com/rest/1.0" + url := fmt.Sprintf("%s/torrents/instantAvailability/%s", baseURL, strings.Join(hashes, "/")) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + + resp, err := rd.client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("error, got response status code %d", resp.StatusCode) + } + + var response AvailabilityResponse + err = json.NewDecoder(resp.Body).Decode(&response) + if err != nil { + return nil, err + } + + return response, nil +} diff --git a/pkg/realdebrid/types.go b/pkg/realdebrid/types.go index b56a62a..8d46785 100644 --- a/pkg/realdebrid/types.go +++ b/pkg/realdebrid/types.go @@ -130,3 +130,17 @@ type User struct { Premium int `json:"premium"` // seconds left as a Premium user Expiration string `json:"expiration"` // jsonDate } + +// key: torrent hash +type AvailabilityResponse map[string]HosterHash + +// key: "rd" +type HosterHash map[string][]SelectionVariant + +// key: file id +type SelectionVariant map[int]FileData + +type FileData struct { + Filename string `json:"filename"` + Filesize int `json:"filesize"` +}