@@ -2,15 +2,14 @@ package downloader
22
33import (
44 "bytes"
5- "context"
65 "encoding/json"
76 "fmt"
8- "log"
97 "net/url"
108 "strings"
119 "time"
1210
1311 cfg "explo/src/config"
12+ "explo/src/debug"
1413 "explo/src/models"
1514 "explo/src/util"
1615)
@@ -174,15 +173,15 @@ type RootFolder struct {
174173 DefaultQualityProfileId int `json:"defaultQualityProfileId"`
175174}
176175
177- func NewLidarr (cfg cfg.Lidarr , discovery , downloadDir string , httpClient * util.HttpClient ) * Lidarr { // init downloader cfg for lidarr
178- return & Lidarr {
176+ func NewLidarr (cfg cfg.Lidarr , discovery , downloadDir string , httpClient * util.HttpClient ) Lidarr { // init downloader cfg for lidarr
177+ return Lidarr {
179178 DownloadDir : downloadDir ,
180179 HttpClient : httpClient ,
181180 Cfg : cfg ,
182181 }
183182}
184183
185- func (c * Lidarr ) QueryTrack (track * models.Track ) error {
184+ func (c Lidarr ) QueryTrack (track * models.Track ) error {
186185
187186 album , err := c .findBestAlbumMatch (track )
188187 if err != nil {
@@ -211,15 +210,12 @@ func (c *Lidarr) QueryTrack(track *models.Track) error {
211210 return nil
212211}
213212
214- func (c * Lidarr ) GetTrack (track * models.Track ) error {
215- ctx := context .Background ()
213+ func (c Lidarr ) GetTrack (track * models.Track ) error {
216214
217215 if track .Present {
218216 return nil
219217 }
220218
221- c .startQueueWorker (ctx , track )
222-
223219 // Get the defaults from the root dir
224220 queryURL := fmt .Sprintf ("%s://%s/api/v1/rootfolder?apiKey=%s" , c .Cfg .Scheme , c .Cfg .URL , c .Cfg .APIKey )
225221
@@ -273,7 +269,7 @@ func (c *Lidarr) GetTrack(track *models.Track) error {
273269 return nil
274270}
275271
276- func (c * Lidarr ) findBestAlbumMatch (track * models.Track ) (* Album , error ) {
272+ func (c Lidarr ) findBestAlbumMatch (track * models.Track ) (* Album , error ) {
277273 escQuery := url .PathEscape (fmt .Sprintf ("%s - %s" , track .Album , track .MainArtist ))
278274 queryURL := fmt .Sprintf ("%s://%s/api/v1/album/lookup?apiKey=%s&term=%s" , c .Cfg .Scheme , c .Cfg .URL , c .Cfg .APIKey , escQuery )
279275
@@ -305,66 +301,73 @@ func (c *Lidarr) findBestAlbumMatch(track *models.Track) (*Album, error) {
305301 return & topMatch , nil
306302}
307303
308- func (c * Lidarr ) startQueueWorker (ctx context.Context , track * models.Track ) {
309- go func () {
310- ticker := time .NewTicker (5 * time .Minute )
311- defer ticker .Stop ()
312-
313- for {
314- select {
315- case <- ctx .Done ():
316- log .Println ("Queue worker stopped" )
317- return
318- case <- ticker .C :
319- if err := c .monitorQueue (track ); err != nil {
320- log .Printf ("Queue worker error: %v" , err )
321- }
322- }
323- }
324- }()
304+ func (c Lidarr ) MonitorDownloads (tracks []* models.Track ) error {
305+ monitorCfg := MonitorConfig {
306+ CheckInterval : 1 * time .Minute ,
307+ MonitorDuration : 15 * time .Minute ,
308+ MigrateDownload : c .Cfg .MigrateDL ,
309+ FromDir : c .Cfg .LidarrDir ,
310+ ToDir : c .DownloadDir ,
311+ }
312+ err := Monitor (
313+ tracks ,
314+ c .getDownloadStatus ,
315+ func (t * models.Track , id string ) { c .cleanupTrack (t , id ) },
316+ moveDownload ,
317+ monitorCfg ,
318+ )
319+ if err != nil {
320+ return err
321+ }
322+ return nil
325323}
326324
327- func (c * Lidarr ) monitorQueue ( track * models. Track ) error {
328- queryURL := fmt . Sprintf ( "%s://%s/ api/v1/queue?apiKey=%s" , c . Cfg . Scheme , c . Cfg . URL , c . Cfg . APIKey )
325+ func (c Lidarr ) getDownloadStatus () ( DownloadStatus , error ) {
326+ reqParams := "/ api/v0/transfers/downloads"
329327
330- body , err := c .HttpClient .MakeRequest ("GET" , queryURL , nil , nil )
328+ body , err := c .HttpClient .MakeRequest ("GET" , c . Cfg . URL + reqParams , nil , nil )
331329 if err != nil {
332- return fmt . Errorf ( "failed to lookup tracks: %w" , err )
330+ return nil , err
333331 }
334332
335- var queue LidarrQueue
336- if err = util .ParseResp (body , & queue ); err != nil {
337- return fmt . Errorf ( "failed to unmarshal query lidarr body: %w" , err )
333+ var status DownloadStatus
334+ if err : = util .ParseResp (body , & status ); err != nil {
335+ return nil , err
338336 }
337+ return status , nil
338+ }
339339
340- for _ , record := range queue .Records {
341- // skip invalid or incomplete entries
342- if record .Size == 0 || record .SizeLeft == 0 {
343- continue
344- }
345-
346- // Check if download is older than 15 minutes and has not progressed
347- age := time .Since (record .Added )
348-
349- if age > 15 * time .Minute && record .Size == record .SizeLeft {
350- log .Printf ("Removing stale download: %s (no progress in %v)" , record .Title , age )
340+ func (c Lidarr ) cleanupTrack (track * models.Track , fileID string ) {
341+ if err := c .deleteSearch (track .ID ); err != nil {
342+ debug .Debug (fmt .Sprintf ("[slskd] failed to delete search request: %v" , err ))
343+ }
344+ if err := c .deleteDownload (track .MainArtistID , fileID ); err != nil {
345+ debug .Debug (fmt .Sprintf ("[slskd] failed to delete download: %v" , err ))
346+ }
347+ }
351348
352- deleteURL := fmt .Sprintf ("%s://%s/api/v1/queue/%v?apiKey=%s" , c .Cfg .Scheme , c .Cfg .URL , record .ID , c .Cfg .APIKey )
349+ func (c Lidarr ) deleteSearch (ID string ) error {
350+ reqParams := fmt .Sprintf ("/api/v0/searches/%s" , ID )
353351
354- _ , err = c .HttpClient .MakeRequest ("DELETE" , deleteURL , nil , nil )
355- if err != nil {
356- return fmt . Errorf ( "failed to delete record %d from queue: %v" , record . ID , err )
357- }
358- continue
359- }
352+ _ , err : = c .HttpClient .MakeRequest ("DELETE" , c . Cfg . URL + reqParams , nil , nil )
353+ if err != nil {
354+ return err
355+ }
356+ return nil
357+ }
360358
361- if record . SizeLeft == 0 && record . TrackHasFileCount > 0 {
362- log . Printf ( "Marking downloaded tracks from album %d as present " , record . AlbumID )
359+ func ( c Lidarr ) deleteDownload ( user , ID string ) error {
360+ reqParams := fmt . Sprintf ( "/api/v0/transfers/downloads/%s/%s " , user , ID )
363361
364- if track .Album == record .Artist [0 ].Album .ForeignAlbumID {
365- track .Present = true
366- }
367- }
362+ // cancel download
363+ if _ , err := c .HttpClient .MakeRequest ("DELETE" , c .Cfg .URL + reqParams + "?remove=false" , nil , nil ); err != nil {
364+ return fmt .Errorf ("soft delete failed: %s" , err .Error ())
365+ }
366+ time .Sleep (1 * time .Second ) // Small buffer between soft and hard delete
367+ // delete download
368+ if _ , err := c .HttpClient .MakeRequest ("DELETE" , c .Cfg .URL + reqParams + "?remove=true" , nil , nil ); err != nil {
369+ return fmt .Errorf ("hard delete failed: %s" , err .Error ())
368370 }
371+
369372 return nil
370373}
0 commit comments