Changelog 0.2.5

This commit is contained in:
Mukhtar Akere
2024-10-01 11:17:31 +01:00
parent f6c6144601
commit f118c5b794
10 changed files with 129 additions and 74 deletions

View File

@@ -68,3 +68,8 @@
- Fix http handler error
- Fix *arrs map failing concurrently
- Fix cache not being updated
#### 0.2.5
- Fix ContentPath not being set prior
- Rewrote Readme
- Cleaned up the code

View File

@@ -68,16 +68,19 @@ Download the binary from the releases page and run it with the config file.
"max_cache_size": 1000,
"qbittorrent": {
"port": "8282",
"username": "admin", // deprecated
"password": "admin", // deprecated
"download_folder": "/media/symlinks/",
"categories": ["sonarr", "radarr"],
"refresh_interval": 5 // in seconds
"refresh_interval": 5
}
}
```
#### Config Notes
##### Max Cache Size
- The `max_cache_size` key is used to set the maximum number of infohashes that can be stored in the availability cache. This is used to prevent round trip to the debrid provider when using the proxy/Qbittorrent
- The default value is `1000`
- The cache is stored in memory and is not persisted on restart
##### Debrid Config
- This config key is important as it's used for both Blackhole and Proxy
@@ -93,6 +96,7 @@ Download the binary from the releases page and run it with the config file.
- The `port` key is the port the qBittorrent will listen on
- The `download_folder` is the folder where the torrents will be downloaded. e.g `/media/symlinks/`
- The `categories` key is used to filter out torrents based on the category. e.g `sonarr`, `radarr`
- The `refresh_interval` key is used to set the interval in minutes to refresh the Arrs Monitored Downloads(it's in seconds). The default value is `5` seconds
### Proxy

View File

@@ -36,6 +36,7 @@ type Torrent struct {
Magnet *common.Magnet `json:"magnet"`
Files []TorrentFile `json:"files"`
Status string `json:"status"`
Added string `json:"added"`
Progress float64 `json:"progress"`
Speed int64 `json:"speed"`
Seeders int `json:"seeders"`

View File

@@ -125,7 +125,7 @@ func (q *QBit) createSymLink(path string, torrentMountPath string, file debrid.T
torrentFilePath := filepath.Join(torrentMountPath, file.Name) // debridFolder/MyTVShow/MyTVShow.S01E01.720p.mkv
err := os.Symlink(torrentFilePath, fullPath)
if err != nil {
q.logger.Printf("Failed to create symlink: %s\n", fullPath)
q.logger.Printf("Failed to create symlink: %s: %v\n", fullPath, err)
}
// Check if the file exists
if !common.FileReady(fullPath) {

View File

@@ -24,6 +24,7 @@ func (q *QBit) AddRoutes(r chi.Router) http.Handler {
r.Get("/resume", q.handleTorrentsResume)
r.Get("/recheck", q.handleTorrentRecheck)
r.Get("/properties", q.handleTorrentProperties)
r.Get("/files", q.handleTorrentFiles)
})
r.Route("/app", func(r chi.Router) {

View File

@@ -5,6 +5,5 @@ import (
)
func (q *QBit) handleLogin(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("Ok."))
_, _ = w.Write([]byte("Ok."))
}

View File

@@ -163,3 +163,13 @@ func (q *QBit) handleTorrentProperties(w http.ResponseWriter, r *http.Request) {
properties := q.GetTorrentProperties(torrent)
JSONResponse(w, properties, http.StatusOK)
}
func (q *QBit) handleTorrentFiles(w http.ResponseWriter, r *http.Request) {
hash := r.URL.Query().Get("hash")
torrent := q.storage.Get(hash)
if torrent == nil {
return
}
files := q.GetTorrentFiles(torrent)
JSONResponse(w, files, http.StatusOK)
}

View File

@@ -58,9 +58,7 @@ func (q *QBit) Process(ctx context.Context, magnet *common.Magnet, category stri
}
return err
}
torrent.ID = debridTorrent.Id
torrent.DebridTorrent = debridTorrent
torrent.Name = debridTorrent.Name
torrent = q.UpdateTorrentMin(torrent, debridTorrent)
q.storage.AddOrUpdate(torrent)
go q.processFiles(torrent, debridTorrent, arr, isSymlink) // We can send async for file processing not to delay the response
return nil
@@ -74,23 +72,14 @@ func (q *QBit) CreateTorrentFromMagnet(magnet *common.Magnet, category string) *
Size: magnet.Size,
Category: category,
State: "downloading",
AddedOn: time.Now().Unix(),
MagnetUri: magnet.Link,
Tracker: "udp://tracker.opentrackr.org:1337",
UpLimit: -1,
DlLimit: -1,
FlPiecePrio: false,
ForceStart: false,
AutoTmm: false,
Availability: 2,
MaxRatio: -1,
MaxSeedingTime: -1,
NumComplete: 10,
NumIncomplete: 0,
NumLeechs: 1,
Ratio: 1,
RatioLimit: 1,
Tracker: "udp://tracker.opentrackr.org:1337",
UpLimit: -1,
DlLimit: -1,
AutoTmm: false,
Ratio: 1,
RatioLimit: 1,
}
return torrent
}
@@ -98,15 +87,17 @@ func (q *QBit) CreateTorrentFromMagnet(magnet *common.Magnet, category string) *
func (q *QBit) processFiles(torrent *Torrent, debridTorrent *debrid.Torrent, arr *debrid.Arr, isSymlink bool) {
for debridTorrent.Status != "downloaded" {
progress := debridTorrent.Progress
q.logger.Printf("Progress: %.2f%%", progress)
q.logger.Printf("RD Download Progress: %.2f%%", progress)
time.Sleep(5 * time.Second)
dbT, err := q.debrid.CheckStatus(debridTorrent, isSymlink)
if err != nil {
q.logger.Printf("Error checking status: %v", err)
q.MarkAsFailed(torrent)
q.RefreshArr(arr)
return
}
debridTorrent = dbT
torrent = q.UpdateTorrentMin(torrent, debridTorrent)
}
if isSymlink {
q.processSymlink(torrent, debridTorrent, arr)

View File

@@ -174,20 +174,20 @@ type Torrent struct {
TorrentPath string `json:"-"`
AddedOn int64 `json:"added_on,omitempty"`
AmountLeft int64 `json:"amount_left,omitempty"`
AmountLeft int64 `json:"amount_left"`
AutoTmm bool `json:"auto_tmm"`
Availability float64 `json:"availability"`
Availability float64 `json:"availability,omitempty"`
Category string `json:"category,omitempty"`
Completed int64 `json:"completed,omitempty"`
Completed int64 `json:"completed"`
CompletionOn int64 `json:"completion_on,omitempty"`
ContentPath string `json:"content_path,omitempty"`
DlLimit int64 `json:"dl_limit,omitempty"`
Dlspeed int64 `json:"dlspeed,omitempty"`
Downloaded int64 `json:"downloaded,omitempty"`
DownloadedSession int64 `json:"downloaded_session,omitempty"`
Eta int64 `json:"eta,omitempty"`
FlPiecePrio bool `json:"f_l_piece_prio"`
ForceStart bool `json:"force_start"`
ContentPath string `json:"content_path"`
DlLimit int64 `json:"dl_limit"`
Dlspeed int64 `json:"dlspeed"`
Downloaded int64 `json:"downloaded"`
DownloadedSession int64 `json:"downloaded_session"`
Eta int64 `json:"eta"`
FlPiecePrio bool `json:"f_l_piece_prio,omitempty"`
ForceStart bool `json:"force_start,omitempty"`
Hash string `json:"hash"`
LastActivity int64 `json:"last_activity,omitempty"`
MagnetUri string `json:"magnet_uri,omitempty"`
@@ -202,7 +202,7 @@ type Torrent struct {
Progress float32 `json:"progress"`
Ratio int64 `json:"ratio,omitempty"`
RatioLimit int64 `json:"ratio_limit,omitempty"`
SavePath string `json:"save_path,omitempty"`
SavePath string `json:"save_path"`
SeedingTimeLimit int64 `json:"seeding_time_limit,omitempty"`
SeenComplete int64 `json:"seen_complete,omitempty"`
SeqDl bool `json:"seq_dl"`
@@ -259,6 +259,17 @@ type TorrentProperties struct {
UpSpeedAvg int64 `json:"up_speed_avg,omitempty"`
}
type TorrentFile struct {
Index int `json:"index,omitempty"`
Name string `json:"name,omitempty"`
Size int64 `json:"size,omitempty"`
Progress int64 `json:"progress,omitempty"`
Priority int64 `json:"priority,omitempty"`
IsSeed bool `json:"is_seed,omitempty"`
PieceRange []int64 `json:"piece_range,omitempty"`
Availability float64 `json:"availability,omitempty"`
}
func NewAppPreferences() *AppPreferences {
preferences := &AppPreferences{
AddTrackers: "",

View File

@@ -16,6 +16,48 @@ func (q *QBit) MarkAsFailed(t *Torrent) *Torrent {
return t
}
func (q *QBit) UpdateTorrentMin(t *Torrent, debridTorrent *debrid.Torrent) *Torrent {
if debridTorrent == nil {
return t
}
addedOn, err := time.Parse(time.RFC3339, debridTorrent.Added)
if err != nil {
addedOn = time.Now()
}
totalSize := float64(debridTorrent.Bytes)
progress := cmp.Or(debridTorrent.Progress, 100.0)
progress = progress / 100.0
sizeCompleted := int64(totalSize * progress)
var speed int64
if debridTorrent.Speed != 0 {
speed = debridTorrent.Speed
}
var eta int64
if speed != 0 {
eta = int64((totalSize - float64(sizeCompleted)) / float64(speed))
}
t.ID = debridTorrent.Id
t.Name = debridTorrent.Name
t.AddedOn = addedOn.Unix()
t.DebridTorrent = debridTorrent
t.Size = int64(totalSize)
t.Completed = sizeCompleted
t.Downloaded = sizeCompleted
t.DownloadedSession = sizeCompleted
t.Uploaded = sizeCompleted
t.UploadedSession = sizeCompleted
t.AmountLeft = int64(totalSize) - sizeCompleted
t.Progress = float32(progress)
t.Eta = eta
t.Dlspeed = speed
t.Upspeed = speed
t.SavePath = filepath.Join(q.DownloadFolder, t.Category) + string(os.PathSeparator)
t.ContentPath = filepath.Join(t.SavePath, t.Name) + string(os.PathSeparator)
return t
}
func (q *QBit) UpdateTorrent(t *Torrent, debridTorrent *debrid.Torrent) *Torrent {
rcLoneMount := q.debrid.GetMountPath()
if debridTorrent == nil && t.ID != "" {
@@ -32,57 +74,33 @@ func (q *QBit) UpdateTorrent(t *Torrent, debridTorrent *debrid.Torrent) *Torrent
if t.TorrentPath == "" {
t.TorrentPath = filepath.Base(debridTorrent.GetMountFolder(rcLoneMount))
}
totalSize := float64(cmp.Or(debridTorrent.Bytes, 1.0))
progress := cmp.Or(debridTorrent.Progress, 100.0)
progress = progress / 100.0
var sizeCompleted int64
sizeCompleted = int64(totalSize * progress)
savePath := filepath.Join(q.DownloadFolder, t.Category) + string(os.PathSeparator)
torrentPath := filepath.Join(savePath, t.TorrentPath) + string(os.PathSeparator)
var speed int64
if debridTorrent.Speed != 0 {
speed = debridTorrent.Speed
}
var eta int64
if speed != 0 {
eta = int64((totalSize - float64(sizeCompleted)) / float64(speed))
}
t.Size = debridTorrent.Bytes
t.DebridTorrent = debridTorrent
t.Completed = sizeCompleted
t.Downloaded = sizeCompleted
t.DownloadedSession = sizeCompleted
t.Uploaded = sizeCompleted
t.UploadedSession = sizeCompleted
t.AmountLeft = int64(totalSize) - sizeCompleted
t.Progress = float32(progress)
t.SavePath = savePath
t = q.UpdateTorrentMin(t, debridTorrent)
t.ContentPath = torrentPath
t.Eta = eta
t.Dlspeed = speed
t.Upspeed = speed
if t.IsReady() {
t.State = "pausedUP"
q.storage.AddOrUpdate(t)
q.storage.Update(t)
return t
}
ticker := time.NewTicker(3 * time.Second)
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if t.IsReady() {
t.State = "pausedUP"
q.storage.AddOrUpdate(t)
ticker.Stop()
q.storage.Update(t)
return t
} else {
return q.UpdateTorrent(t, debridTorrent)
}
updatedT := q.UpdateTorrent(t, debridTorrent)
t = updatedT
case <-time.After(10 * time.Minute): // Add a timeout
return t
}
}
}
@@ -123,3 +141,18 @@ func (q *QBit) GetTorrentProperties(t *Torrent) *TorrentProperties {
ShareRatio: 100,
}
}
func (q *QBit) GetTorrentFiles(t *Torrent) []*TorrentFile {
files := make([]*TorrentFile, 0)
if t.DebridTorrent == nil {
return files
}
for index, file := range t.DebridTorrent.Files {
files = append(files, &TorrentFile{
Index: index,
Name: file.Path,
Size: file.Size,
})
}
return files
}