2018-11-23 07:03:32 +00:00
|
|
|
using System;
|
|
|
|
using System.Linq;
|
|
|
|
using NzbDrone.Common.Extensions;
|
|
|
|
using NzbDrone.Core.Datastore;
|
|
|
|
using NzbDrone.Core.Datastore.Events;
|
|
|
|
using NzbDrone.Core.Download.Pending;
|
|
|
|
using NzbDrone.Core.Messaging.Events;
|
2019-06-14 03:54:25 +00:00
|
|
|
using NzbDrone.Core.Profiles;
|
|
|
|
using NzbDrone.Core.Qualities;
|
2018-11-23 07:03:32 +00:00
|
|
|
using NzbDrone.Core.Queue;
|
|
|
|
using NzbDrone.SignalR;
|
|
|
|
using Radarr.Http;
|
|
|
|
using Radarr.Http.Extensions;
|
|
|
|
|
2019-12-03 01:36:18 +00:00
|
|
|
namespace Radarr.Api.V3.Queue
|
2018-11-23 07:03:32 +00:00
|
|
|
{
|
|
|
|
public class QueueModule : RadarrRestModuleWithSignalR<QueueResource, NzbDrone.Core.Queue.Queue>,
|
|
|
|
IHandle<QueueUpdatedEvent>, IHandle<PendingReleasesUpdatedEvent>
|
|
|
|
{
|
|
|
|
private readonly IQueueService _queueService;
|
|
|
|
private readonly IPendingReleaseService _pendingReleaseService;
|
|
|
|
|
2019-06-14 03:54:25 +00:00
|
|
|
private readonly QualityModelComparer QUALITY_COMPARER;
|
|
|
|
|
|
|
|
public QueueModule(IBroadcastSignalRMessage broadcastSignalRMessage,
|
|
|
|
IQueueService queueService,
|
|
|
|
IPendingReleaseService pendingReleaseService,
|
|
|
|
ProfileService qualityProfileService)
|
2018-11-23 07:03:32 +00:00
|
|
|
: base(broadcastSignalRMessage)
|
|
|
|
{
|
|
|
|
_queueService = queueService;
|
|
|
|
_pendingReleaseService = pendingReleaseService;
|
|
|
|
GetResourcePaged = GetQueue;
|
2019-06-14 03:54:25 +00:00
|
|
|
|
|
|
|
QUALITY_COMPARER = new QualityModelComparer(qualityProfileService.GetDefaultProfile(string.Empty));
|
2018-11-23 07:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private PagingResource<QueueResource> GetQueue(PagingResource<QueueResource> pagingResource)
|
|
|
|
{
|
|
|
|
var pagingSpec = pagingResource.MapToPagingSpec<QueueResource, NzbDrone.Core.Queue.Queue>("timeleft", SortDirection.Ascending);
|
2019-06-14 03:54:25 +00:00
|
|
|
var includeUnknownMovieItems = Request.GetBooleanQueryParameter("includeUnknownMovieItems");
|
|
|
|
var includeMovie = Request.GetBooleanQueryParameter("includeMovie");
|
2018-11-23 07:03:32 +00:00
|
|
|
|
2019-06-14 03:54:25 +00:00
|
|
|
return ApplyToPage((spec) => GetQueue(spec, includeUnknownMovieItems), pagingSpec, (q) => MapToResource(q, includeMovie));
|
2018-11-23 07:03:32 +00:00
|
|
|
}
|
|
|
|
|
2019-06-14 03:54:25 +00:00
|
|
|
private PagingSpec<NzbDrone.Core.Queue.Queue> GetQueue(PagingSpec<NzbDrone.Core.Queue.Queue> pagingSpec, bool includeUnknownMovieItems)
|
2018-11-23 07:03:32 +00:00
|
|
|
{
|
|
|
|
var ascending = pagingSpec.SortDirection == SortDirection.Ascending;
|
|
|
|
var orderByFunc = GetOrderByFunc(pagingSpec);
|
|
|
|
|
|
|
|
var queue = _queueService.GetQueue();
|
2019-06-14 03:54:25 +00:00
|
|
|
var filteredQueue = includeUnknownMovieItems ? queue : queue.Where(q => q.Movie != null);
|
2018-11-23 07:03:32 +00:00
|
|
|
var pending = _pendingReleaseService.GetPendingQueue();
|
2019-06-14 03:54:25 +00:00
|
|
|
var fullQueue = filteredQueue.Concat(pending).ToList();
|
2018-11-23 07:03:32 +00:00
|
|
|
IOrderedEnumerable<NzbDrone.Core.Queue.Queue> ordered;
|
|
|
|
|
|
|
|
if (pagingSpec.SortKey == "timeleft")
|
|
|
|
{
|
2019-06-14 03:54:25 +00:00
|
|
|
ordered = ascending
|
|
|
|
? fullQueue.OrderBy(q => q.Timeleft, new TimeleftComparer())
|
|
|
|
: fullQueue.OrderByDescending(q => q.Timeleft, new TimeleftComparer());
|
2018-11-23 07:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (pagingSpec.SortKey == "estimatedCompletionTime")
|
|
|
|
{
|
2019-06-14 03:54:25 +00:00
|
|
|
ordered = ascending
|
|
|
|
? fullQueue.OrderBy(q => q.EstimatedCompletionTime, new EstimatedCompletionTimeComparer())
|
|
|
|
: fullQueue.OrderByDescending(q => q.EstimatedCompletionTime,
|
|
|
|
new EstimatedCompletionTimeComparer());
|
2018-11-23 07:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (pagingSpec.SortKey == "protocol")
|
|
|
|
{
|
2019-06-14 03:54:25 +00:00
|
|
|
ordered = ascending
|
|
|
|
? fullQueue.OrderBy(q => q.Protocol)
|
|
|
|
: fullQueue.OrderByDescending(q => q.Protocol);
|
2018-11-23 07:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (pagingSpec.SortKey == "indexer")
|
|
|
|
{
|
2019-06-14 03:54:25 +00:00
|
|
|
ordered = ascending
|
|
|
|
? fullQueue.OrderBy(q => q.Indexer, StringComparer.InvariantCultureIgnoreCase)
|
|
|
|
: fullQueue.OrderByDescending(q => q.Indexer, StringComparer.InvariantCultureIgnoreCase);
|
2018-11-23 07:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
else if (pagingSpec.SortKey == "downloadClient")
|
|
|
|
{
|
2019-06-14 03:54:25 +00:00
|
|
|
ordered = ascending
|
|
|
|
? fullQueue.OrderBy(q => q.DownloadClient, StringComparer.InvariantCultureIgnoreCase)
|
|
|
|
: fullQueue.OrderByDescending(q => q.DownloadClient, StringComparer.InvariantCultureIgnoreCase);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (pagingSpec.SortKey == "quality")
|
|
|
|
{
|
|
|
|
ordered = ascending
|
|
|
|
? fullQueue.OrderBy(q => q.Quality, QUALITY_COMPARER)
|
|
|
|
: fullQueue.OrderByDescending(q => q.Quality, QUALITY_COMPARER);
|
2018-11-23 07:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ordered = ascending ? fullQueue.OrderBy(orderByFunc) : fullQueue.OrderByDescending(orderByFunc);
|
|
|
|
}
|
|
|
|
|
|
|
|
ordered = ordered.ThenByDescending(q => q.Size == 0 ? 0 : 100 - q.Sizeleft / q.Size * 100);
|
|
|
|
|
|
|
|
pagingSpec.Records = ordered.Skip((pagingSpec.Page - 1) * pagingSpec.PageSize).Take(pagingSpec.PageSize).ToList();
|
|
|
|
pagingSpec.TotalRecords = fullQueue.Count;
|
|
|
|
|
|
|
|
if (pagingSpec.Records.Empty() && pagingSpec.Page > 1)
|
|
|
|
{
|
|
|
|
pagingSpec.Page = (int)Math.Max(Math.Ceiling((decimal)(pagingSpec.TotalRecords / pagingSpec.PageSize)), 1);
|
|
|
|
pagingSpec.Records = ordered.Skip((pagingSpec.Page - 1) * pagingSpec.PageSize).Take(pagingSpec.PageSize).ToList();
|
|
|
|
}
|
|
|
|
|
|
|
|
return pagingSpec;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Func<NzbDrone.Core.Queue.Queue, Object> GetOrderByFunc(PagingSpec<NzbDrone.Core.Queue.Queue> pagingSpec)
|
|
|
|
{
|
|
|
|
switch (pagingSpec.SortKey)
|
|
|
|
{
|
2019-06-14 03:54:25 +00:00
|
|
|
case "status":
|
2019-12-22 21:24:11 +00:00
|
|
|
return q => q.Status;
|
2018-11-23 07:03:32 +00:00
|
|
|
case "movie.sortTitle":
|
|
|
|
return q => q.Movie.SortTitle;
|
2019-04-13 03:25:58 +00:00
|
|
|
case "title":
|
|
|
|
return q => q.Title;
|
2019-06-14 03:54:25 +00:00
|
|
|
case "language":
|
|
|
|
return q => q.Languages;
|
2018-11-23 07:03:32 +00:00
|
|
|
case "quality":
|
|
|
|
return q => q.Quality;
|
|
|
|
case "progress":
|
|
|
|
// Avoid exploding if a download's size is 0
|
|
|
|
return q => 100 - q.Sizeleft / Math.Max(q.Size * 100, 1);
|
|
|
|
default:
|
|
|
|
return q => q.Timeleft;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private QueueResource MapToResource(NzbDrone.Core.Queue.Queue queueItem, bool includeMovie)
|
|
|
|
{
|
|
|
|
return queueItem.ToResource(includeMovie);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Handle(QueueUpdatedEvent message)
|
|
|
|
{
|
|
|
|
BroadcastResourceChange(ModelAction.Sync);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Handle(PendingReleasesUpdatedEvent message)
|
|
|
|
{
|
|
|
|
BroadcastResourceChange(ModelAction.Sync);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|