193 lines
4.7 KiB
Go
193 lines
4.7 KiB
Go
package debrid
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/anacrolix/torrent/metainfo"
|
|
"github.com/rs/zerolog"
|
|
"github.com/sirrobot01/debrid-blackhole/common"
|
|
"github.com/sirrobot01/debrid-blackhole/pkg/arr"
|
|
"path/filepath"
|
|
)
|
|
|
|
type BaseDebrid struct {
|
|
Name string
|
|
Host string `json:"host"`
|
|
APIKey string
|
|
DownloadUncached bool
|
|
client *common.RLHTTPClient
|
|
cache *common.Cache
|
|
MountPath string
|
|
logger zerolog.Logger
|
|
CheckCached bool
|
|
}
|
|
|
|
type Service interface {
|
|
SubmitMagnet(torrent *Torrent) (*Torrent, error)
|
|
CheckStatus(torrent *Torrent, isSymlink bool) (*Torrent, error)
|
|
GetDownloadLinks(torrent *Torrent) error
|
|
DeleteTorrent(torrent *Torrent)
|
|
IsAvailable(infohashes []string) map[string]bool
|
|
GetMountPath() string
|
|
GetCheckCached() bool
|
|
GetTorrent(id string) (*Torrent, error)
|
|
GetName() string
|
|
GetLogger() zerolog.Logger
|
|
}
|
|
|
|
func NewDebrid(debs []common.DebridConfig, maxCachedSize int) *DebridService {
|
|
debrids := make([]Service, 0)
|
|
// Divide the cache size by the number of debrids
|
|
maxCacheSize := maxCachedSize / len(debs)
|
|
|
|
for _, dc := range debs {
|
|
d := createDebrid(dc, common.NewCache(maxCacheSize))
|
|
logger := d.GetLogger()
|
|
logger.Info().Msg("Debrid Service started")
|
|
debrids = append(debrids, d)
|
|
}
|
|
d := &DebridService{debrids: debrids, lastUsed: 0}
|
|
return d
|
|
}
|
|
|
|
func createDebrid(dc common.DebridConfig, cache *common.Cache) Service {
|
|
switch dc.Name {
|
|
case "realdebrid":
|
|
return NewRealDebrid(dc, cache)
|
|
case "torbox":
|
|
return NewTorbox(dc, cache)
|
|
case "debridlink":
|
|
return NewDebridLink(dc, cache)
|
|
case "alldebrid":
|
|
return NewAllDebrid(dc, cache)
|
|
default:
|
|
return NewRealDebrid(dc, cache)
|
|
}
|
|
}
|
|
|
|
func GetTorrentInfo(filePath string) (*Torrent, error) {
|
|
// Open and read the .torrent file
|
|
if filepath.Ext(filePath) == ".torrent" {
|
|
return getTorrentInfo(filePath)
|
|
} else {
|
|
return torrentFromMagnetFile(filePath)
|
|
}
|
|
|
|
}
|
|
|
|
func torrentFromMagnetFile(filePath string) (*Torrent, error) {
|
|
magnetLink := common.OpenMagnetFile(filePath)
|
|
magnet, err := common.GetMagnetInfo(magnetLink)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
torrent := &Torrent{
|
|
InfoHash: magnet.InfoHash,
|
|
Name: magnet.Name,
|
|
Size: magnet.Size,
|
|
Magnet: magnet,
|
|
Filename: filePath,
|
|
}
|
|
return torrent, nil
|
|
}
|
|
|
|
func getTorrentInfo(filePath string) (*Torrent, error) {
|
|
mi, err := metainfo.LoadFromFile(filePath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
hash := mi.HashInfoBytes()
|
|
infoHash := hash.HexString()
|
|
info, err := mi.UnmarshalInfo()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
infoLength := info.Length
|
|
magnet := &common.Magnet{
|
|
InfoHash: infoHash,
|
|
Name: info.Name,
|
|
Size: infoLength,
|
|
Link: mi.Magnet(&hash, &info).String(),
|
|
}
|
|
torrent := &Torrent{
|
|
InfoHash: infoHash,
|
|
Name: info.Name,
|
|
Size: infoLength,
|
|
Magnet: magnet,
|
|
Filename: filePath,
|
|
}
|
|
return torrent, nil
|
|
}
|
|
|
|
func GetLocalCache(infohashes []string, cache *common.Cache) ([]string, map[string]bool) {
|
|
result := make(map[string]bool)
|
|
hashes := make([]string, 0)
|
|
|
|
if len(infohashes) == 0 {
|
|
return hashes, result
|
|
}
|
|
if len(infohashes) == 1 {
|
|
if cache.Exists(infohashes[0]) {
|
|
return hashes, map[string]bool{infohashes[0]: true}
|
|
}
|
|
return infohashes, result
|
|
}
|
|
|
|
cachedHashes := cache.GetMultiple(infohashes)
|
|
for _, h := range infohashes {
|
|
_, exists := cachedHashes[h]
|
|
if !exists {
|
|
hashes = append(hashes, h)
|
|
} else {
|
|
result[h] = true
|
|
}
|
|
}
|
|
|
|
return infohashes, result
|
|
}
|
|
|
|
func ProcessTorrent(d *DebridService, magnet *common.Magnet, a *arr.Arr, isSymlink bool) (*Torrent, error) {
|
|
debridTorrent := &Torrent{
|
|
InfoHash: magnet.InfoHash,
|
|
Magnet: magnet,
|
|
Name: magnet.Name,
|
|
Arr: a,
|
|
Size: magnet.Size,
|
|
}
|
|
|
|
errs := make([]error, 0)
|
|
|
|
for index, db := range d.debrids {
|
|
logger := db.GetLogger()
|
|
logger.Info().Msgf("Processing debrid: %s", db.GetName())
|
|
|
|
logger.Info().Msgf("Torrent Hash: %s", debridTorrent.InfoHash)
|
|
if db.GetCheckCached() {
|
|
hash, exists := db.IsAvailable([]string{debridTorrent.InfoHash})[debridTorrent.InfoHash]
|
|
if !exists || !hash {
|
|
logger.Info().Msgf("Torrent: %s is not cached", debridTorrent.Name)
|
|
continue
|
|
} else {
|
|
logger.Info().Msgf("Torrent: %s is cached(or downloading)", debridTorrent.Name)
|
|
}
|
|
}
|
|
|
|
dbt, err := db.SubmitMagnet(debridTorrent)
|
|
if dbt != nil {
|
|
dbt.Debrid = db
|
|
dbt.Arr = a
|
|
}
|
|
if err != nil || dbt == nil || dbt.Id == "" {
|
|
errs = append(errs, err)
|
|
continue
|
|
}
|
|
logger.Info().Msgf("Torrent: %s submitted to %s", dbt.Name, db.GetName())
|
|
d.lastUsed = index
|
|
return db.CheckStatus(dbt, isSymlink)
|
|
}
|
|
err := fmt.Errorf("failed to process torrent")
|
|
for _, e := range errs {
|
|
err = fmt.Errorf("%w\n%w", err, e)
|
|
}
|
|
return nil, err
|
|
}
|