feat: add download tracking endpoints (sections 4.1, 4.2, 4.3, 4.4)
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/fujin/music-agregator/internal/database"
|
||||
"github.com/fujin/music-agregator/internal/torrent"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type QueueSyncResult struct {
|
||||
Synced int `json:"synced"`
|
||||
Updated int `json:"updated"`
|
||||
}
|
||||
|
||||
func SyncDownloadQueue(ctx context.Context, db *database.DB, torrentService *TorrentService) (*QueueSyncResult, error) {
|
||||
if !torrentService.IsConfigured() {
|
||||
return &QueueSyncResult{}, nil
|
||||
}
|
||||
|
||||
torrents, err := torrentService.ListTorrents(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
torrentMap := make(map[string]torrent.TorrentInfo)
|
||||
for _, t := range torrents {
|
||||
torrentMap[t.Hash] = t
|
||||
}
|
||||
|
||||
queueItems, err := db.ListDownloadQueue(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var synced, updated int
|
||||
for _, item := range queueItems {
|
||||
if item.TorrentHash == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
synced++
|
||||
t, exists := torrentMap[*item.TorrentHash]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
newStatus := mapTorrentState(t.State)
|
||||
sizeLeft := int64(float64(item.Size) * (1 - t.Progress))
|
||||
|
||||
if newStatus != item.Status || item.Progress != float32(t.Progress) {
|
||||
if err := db.UpdateDownloadQueueProgress(ctx, item.ID, float32(t.Progress), sizeLeft, newStatus); err != nil {
|
||||
continue
|
||||
}
|
||||
updated++
|
||||
|
||||
if newStatus == "completed" && item.AlbumID != nil {
|
||||
db.RemoveFromWantedAlbums(ctx, *item.AlbumID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &QueueSyncResult{Synced: synced, Updated: updated}, nil
|
||||
}
|
||||
|
||||
func mapTorrentState(state torrent.TorrentState) string {
|
||||
switch state {
|
||||
case torrent.StateDownloading:
|
||||
return "downloading"
|
||||
case torrent.StateSeeding:
|
||||
return "completed"
|
||||
case torrent.StatePaused:
|
||||
return "paused"
|
||||
case torrent.StateQueued:
|
||||
return "queued"
|
||||
case torrent.StateChecking:
|
||||
return "checking"
|
||||
case torrent.StateError:
|
||||
return "failed"
|
||||
default:
|
||||
return "queued"
|
||||
}
|
||||
}
|
||||
|
||||
func HandleFailedDownload(ctx context.Context, db *database.DB, queueID uuid.UUID, errorMessage string) error {
|
||||
item, err := db.GetDownloadQueueItem(ctx, queueID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.UpdateDownloadQueueStatus(ctx, queueID, "failed", &errorMessage); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if item.ArtistID != nil && item.AlbumID != nil {
|
||||
if err := db.AddToBlocklist(ctx, *item.ArtistID, *item.AlbumID, item.Title, item.TorrentHash, item.Indexer); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if item.AlbumID != nil {
|
||||
if err := db.AddToWantedAlbums(ctx, *item.AlbumID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type BlocklistResult struct {
|
||||
Blocklisted bool `json:"blocklisted"`
|
||||
Removed bool `json:"removed"`
|
||||
}
|
||||
|
||||
func BlocklistAndRemove(ctx context.Context, db *database.DB, torrentService *TorrentService, queueID uuid.UUID) (*BlocklistResult, error) {
|
||||
item, err := db.GetDownloadQueueItem(ctx, queueID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &BlocklistResult{}
|
||||
|
||||
if item.ArtistID != nil {
|
||||
albumID := item.AlbumID
|
||||
if albumID == nil {
|
||||
albumID = &uuid.Nil
|
||||
}
|
||||
if err := db.AddToBlocklist(ctx, *item.ArtistID, *albumID, item.Title, item.TorrentHash, item.Indexer); err == nil {
|
||||
result.Blocklisted = true
|
||||
}
|
||||
}
|
||||
|
||||
if item.TorrentHash != nil && torrentService.IsConfigured() {
|
||||
torrentService.RemoveTorrent(ctx, *item.TorrentHash, true)
|
||||
}
|
||||
|
||||
if err := db.DeleteDownloadQueueItem(ctx, queueID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.Removed = true
|
||||
|
||||
if item.AlbumID != nil {
|
||||
db.AddToWantedAlbums(ctx, *item.AlbumID)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
Reference in New Issue
Block a user