Files
decypharr/debrid/realdebrid.go
Mukhtar Akere 74791d6e62 Features:
- Make Blackhole and Proxy optional
- Query all Hashes at once, speeeding up the process
- refractor the code a little bit
2024-08-26 20:13:48 +01:00

165 lines
4.3 KiB
Go

package debrid
import (
"encoding/json"
"fmt"
"goBlack/common"
"goBlack/debrid/structs"
"log"
"net/http"
gourl "net/url"
"path/filepath"
"strconv"
"strings"
)
type RealDebrid struct {
Host string `json:"host"`
APIKey string
DownloadUncached bool
client *common.RLHTTPClient
}
func (r *RealDebrid) Process(arr *Arr, magnet string) (*Torrent, error) {
torrent, err := GetTorrentInfo(magnet)
torrent.Arr = arr
if err != nil {
return torrent, err
}
log.Printf("Torrent Name: %s", torrent.Name)
if !r.DownloadUncached {
if !r.IsAvailable([]string{torrent.InfoHash})[torrent.InfoHash] {
return torrent, fmt.Errorf("torrent is not cached")
}
log.Printf("Torrent: %s is cached", torrent.Name)
}
torrent, err = r.SubmitMagnet(torrent)
if err != nil || torrent.Id == "" {
return nil, err
}
return r.CheckStatus(torrent)
}
func (r *RealDebrid) IsAvailable(infohashes []string) map[string]bool {
hashes := strings.Join(infohashes, "/")
result := make(map[string]bool)
url := fmt.Sprintf("%s/torrents/instantAvailability/%s", r.Host, hashes)
resp, err := r.client.MakeRequest(http.MethodGet, url, nil)
if err != nil {
log.Println(url)
log.Println("Error checking availability:", err)
return result
}
var data structs.RealDebridAvailabilityResponse
err = json.Unmarshal(resp, &data)
if err != nil {
log.Println("Error marshalling availability:", err)
return result
}
for _, h := range infohashes {
hosters, exists := data[strings.ToLower(h)]
if !exists || len(hosters.Rd) < 1 {
result[h] = false
} else {
result[h] = true
}
}
return result
}
func (r *RealDebrid) SubmitMagnet(torrent *Torrent) (*Torrent, error) {
url := fmt.Sprintf("%s/torrents/addMagnet", r.Host)
payload := gourl.Values{
"magnet": {torrent.Magnet.Link},
}
var data structs.RealDebridAddMagnetSchema
resp, err := r.client.MakeRequest(http.MethodPost, url, strings.NewReader(payload.Encode()))
if err != nil {
return nil, err
}
err = json.Unmarshal(resp, &data)
log.Printf("Torrent: %s added with id: %s\n", torrent.Name, data.Id)
torrent.Id = data.Id
return torrent, nil
}
func (r *RealDebrid) CheckStatus(torrent *Torrent) (*Torrent, error) {
url := fmt.Sprintf("%s/torrents/info/%s", r.Host, torrent.Id)
for {
resp, err := r.client.MakeRequest(http.MethodGet, url, nil)
if err != nil {
return torrent, err
}
var data structs.RealDebridTorrentInfo
err = json.Unmarshal(resp, &data)
status := data.Status
torrent.Folder = common.RemoveExtension(data.OriginalFilename)
if status == "error" || status == "dead" || status == "magnet_error" {
return torrent, fmt.Errorf("torrent: %s has error", torrent.Name)
} else if status == "waiting_files_selection" {
files := make([]TorrentFile, 0)
for _, f := range data.Files {
name := f.Path
if !common.RegexMatch(common.VIDEOMATCH, name) && !common.RegexMatch(common.SUBMATCH, name) {
continue
}
fileId := f.ID
file := &TorrentFile{
Name: name,
Path: filepath.Join(torrent.Folder, name),
Size: int64(f.Bytes),
Id: strconv.Itoa(fileId),
}
files = append(files, *file)
}
torrent.Files = files
if len(files) == 0 {
return torrent, fmt.Errorf("no video files found")
}
filesId := make([]string, 0)
for _, f := range files {
filesId = append(filesId, f.Id)
}
p := gourl.Values{
"files": {strings.Join(filesId, ",")},
}
payload := strings.NewReader(p.Encode())
_, err = r.client.MakeRequest(http.MethodPost, fmt.Sprintf("%s/torrents/selectFiles/%s", r.Host, torrent.Id), payload)
if err != nil {
return torrent, err
}
} else if status == "downloaded" {
log.Printf("Torrent: %s downloaded\n", torrent.Name)
err = r.DownloadLink(torrent)
if err != nil {
return torrent, err
}
break
} else if status == "downloading" {
return torrent, fmt.Errorf("torrent is uncached")
}
}
return torrent, nil
}
func (r *RealDebrid) DownloadLink(torrent *Torrent) error {
return nil
}
func NewRealDebrid(dc common.DebridConfig) *RealDebrid {
rl := common.ParseRateLimit(dc.RateLimit)
headers := map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", dc.APIKey),
}
client := common.NewRLHTTPClient(rl, headers)
return &RealDebrid{
Host: dc.Host,
APIKey: dc.APIKey,
DownloadUncached: dc.DownloadUncached,
client: client,
}
}