Fixed: Allow downloading any search result (#525)

* Allow downloading any search result

Ones that couldn't be parsed get a red icon

* Not required - initialized to false

* Add a warning the the queue page for manual downloads
pull/504/head
ta264 6 years ago committed by Qstick
parent eedaa2a7b8
commit c98b86b413

@ -19,5 +19,5 @@
.actions { .actions {
composes: cell from 'Components/Table/Cells/TableRowCell.css'; composes: cell from 'Components/Table/Cells/TableRowCell.css';
width: 70px; width: 90px;
} }

@ -1,6 +1,6 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { icons, kinds } from 'Helpers/Props'; import { icons, kinds, tooltipPositions } from 'Helpers/Props';
import IconButton from 'Components/Link/IconButton'; import IconButton from 'Components/Link/IconButton';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
import ProgressBar from 'Components/ProgressBar'; import ProgressBar from 'Components/ProgressBar';
@ -8,6 +8,8 @@ import TableRow from 'Components/Table/TableRow';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRowCell from 'Components/Table/Cells/TableRowCell';
import TableSelectCell from 'Components/Table/Cells/TableSelectCell'; import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
import Icon from 'Components/Icon';
import Popover from 'Components/Tooltip/Popover';
import ProtocolLabel from 'Activity/Queue/ProtocolLabel'; import ProtocolLabel from 'Activity/Queue/ProtocolLabel';
import AlbumTitleLink from 'Album/AlbumTitleLink'; import AlbumTitleLink from 'Album/AlbumTitleLink';
import TrackQuality from 'Album/TrackQuality'; import TrackQuality from 'Album/TrackQuality';
@ -74,6 +76,7 @@ class QueueRow extends Component {
protocol, protocol,
indexer, indexer,
downloadClient, downloadClient,
downloadForced,
estimatedCompletionTime, estimatedCompletionTime,
timeleft, timeleft,
size, size,
@ -249,6 +252,21 @@ class QueueRow extends Component {
key={name} key={name}
className={styles.actions} className={styles.actions}
> >
{
downloadForced &&
<Popover
anchor={
<Icon
name={icons.DANGER}
kind={kinds.DANGER}
/>
}
title="Manual Download"
body="This release failed parsing checks and was manually downloaded from an interactive search. Import is likely to fail."
position={tooltipPositions.LEFT}
/>
}
{ {
showInteractiveImport && showInteractiveImport &&
<IconButton <IconButton
@ -314,6 +332,7 @@ QueueRow.propTypes = {
protocol: PropTypes.string.isRequired, protocol: PropTypes.string.isRequired,
indexer: PropTypes.string, indexer: PropTypes.string,
downloadClient: PropTypes.string, downloadClient: PropTypes.string,
downloadForced: PropTypes.bool.isRequired,
estimatedCompletionTime: PropTypes.string, estimatedCompletionTime: PropTypes.string,
timeleft: PropTypes.string, timeleft: PropTypes.string,
size: PropTypes.number, size: PropTypes.number,

@ -79,7 +79,7 @@ class RemoveQueueItemModal extends Component {
type={inputTypes.CHECK} type={inputTypes.CHECK}
name="blacklist" name="blacklist"
value={blacklist} value={blacklist}
helpText="Prevents Lidarr from automatically grabbing this album again" helpText="Prevents Lidarr from automatically grabbing these files again"
onChange={this.onBlacklistChange} onChange={this.onBlacklistChange}
/> />
</FormGroup> </FormGroup>

@ -156,14 +156,13 @@ class InteractiveSearchRow extends Component {
<TableRowCell className={styles.download}> <TableRowCell className={styles.download}>
{ {
downloadAllowed && <SpinnerIconButton
<SpinnerIconButton name={getDownloadIcon(isGrabbing, isGrabbed, grabError)}
name={getDownloadIcon(isGrabbing, isGrabbed, grabError)} kind={grabError || !downloadAllowed ? kinds.DANGER : kinds.DEFAULT}
kind={grabError ? kinds.DANGER : kinds.DEFAULT} title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)} isSpinning={isGrabbing}
isSpinning={isGrabbing} onPress={this.onGrabPress}
onPress={this.onGrabPress} />
/>
} }
</TableRowCell> </TableRowCell>
</TableRow> </TableRow>

@ -46,7 +46,6 @@ namespace Lidarr.Api.V1.Indexers
GetResourceAll = GetReleases; GetResourceAll = GetReleases;
Post["/"] = x => DownloadRelease(this.Bind<ReleaseResource>()); Post["/"] = x => DownloadRelease(this.Bind<ReleaseResource>());
PostValidator.RuleFor(s => s.DownloadAllowed).Equal(true);
PostValidator.RuleFor(s => s.IndexerId).ValidId(); PostValidator.RuleFor(s => s.IndexerId).ValidId();
PostValidator.RuleFor(s => s.Guid).NotEmpty(); PostValidator.RuleFor(s => s.Guid).NotEmpty();

@ -30,6 +30,7 @@ namespace Lidarr.Api.V1.Queue
public DownloadProtocol Protocol { get; set; } public DownloadProtocol Protocol { get; set; }
public string DownloadClient { get; set; } public string DownloadClient { get; set; }
public string Indexer { get; set; } public string Indexer { get; set; }
public bool DownloadForced { get; set; }
} }
public static class QueueResourceMapper public static class QueueResourceMapper
@ -58,7 +59,8 @@ namespace Lidarr.Api.V1.Queue
DownloadId = model.DownloadId, DownloadId = model.DownloadId,
Protocol = model.Protocol, Protocol = model.Protocol,
DownloadClient = model.DownloadClient, DownloadClient = model.DownloadClient,
Indexer = model.Indexer Indexer = model.Indexer,
DownloadForced = model.DownloadForced
}; };
} }

@ -62,6 +62,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Cutoff = Language.Spanish Cutoff = Language.Spanish
}).Build(); }).Build();
remoteAlbum.DownloadAllowed = true;
return remoteAlbum; return remoteAlbum;
} }

@ -94,10 +94,20 @@ namespace NzbDrone.Core.DecisionEngine
if (remoteAlbum.Artist == null) if (remoteAlbum.Artist == null)
{ {
decision = new DownloadDecision(remoteAlbum, new Rejection("Unknown Artist")); decision = new DownloadDecision(remoteAlbum, new Rejection("Unknown Artist"));
// shove in the searched artist in case of forced download in interactive search
if (searchCriteria != null)
{
remoteAlbum.Artist = searchCriteria.Artist;
remoteAlbum.Albums = searchCriteria.Albums;
}
} }
else if (remoteAlbum.Albums.Empty()) else if (remoteAlbum.Albums.Empty())
{ {
decision = new DownloadDecision(remoteAlbum, new Rejection("Unable to parse albums from release name")); decision = new DownloadDecision(remoteAlbum, new Rejection("Unable to parse albums from release name"));
if (searchCriteria != null)
{
remoteAlbum.Albums = searchCriteria.Albums;
}
} }
else else
{ {

@ -21,13 +21,13 @@ namespace NzbDrone.Core.DecisionEngine
public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions) public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions)
{ {
return decisions.Where(c => c.RemoteAlbum.Artist != null) return decisions.Where(c => c.RemoteAlbum.DownloadAllowed)
.GroupBy(c => c.RemoteAlbum.Artist.Id, (artistId, downloadDecisions) => .GroupBy(c => c.RemoteAlbum.Artist.Id, (artistId, downloadDecisions) =>
{ {
return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService)); return downloadDecisions.OrderByDescending(decision => decision, new DownloadDecisionComparer(_delayProfileService));
}) })
.SelectMany(c => c) .SelectMany(c => c)
.Union(decisions.Where(c => c.RemoteAlbum.Artist == null)) .Union(decisions.Where(c => !c.RemoteAlbum.DownloadAllowed))
.ToList(); .ToList();
} }
} }

@ -162,6 +162,7 @@ namespace NzbDrone.Core.History
history.Data.Add("DownloadUrl", message.Album.Release.DownloadUrl); history.Data.Add("DownloadUrl", message.Album.Release.DownloadUrl);
history.Data.Add("Guid", message.Album.Release.Guid); history.Data.Add("Guid", message.Album.Release.Guid);
history.Data.Add("Protocol", ((int)message.Album.Release.DownloadProtocol).ToString()); history.Data.Add("Protocol", ((int)message.Album.Release.DownloadProtocol).ToString());
history.Data.Add("DownloadForced", (!message.Album.DownloadAllowed).ToString());
if (!message.Album.ParsedAlbumInfo.ReleaseHash.IsNullOrWhiteSpace()) if (!message.Album.ParsedAlbumInfo.ReleaseHash.IsNullOrWhiteSpace())
{ {

@ -28,5 +28,6 @@ namespace NzbDrone.Core.Queue
public string DownloadClient { get; set; } public string DownloadClient { get; set; }
public string Indexer { get; set; } public string Indexer { get; set; }
public string ErrorMessage { get; set; } public string ErrorMessage { get; set; }
public bool DownloadForced { get; set; }
} }
} }

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using NzbDrone.Common.Crypto; using NzbDrone.Common.Crypto;
using NzbDrone.Core.Download.TrackedDownloads; using NzbDrone.Core.Download.TrackedDownloads;
using NzbDrone.Core.History;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Music; using NzbDrone.Core.Music;
@ -19,10 +20,13 @@ namespace NzbDrone.Core.Queue
{ {
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private static List<Queue> _queue = new List<Queue>(); private static List<Queue> _queue = new List<Queue>();
private readonly IHistoryService _historyService;
public QueueService(IEventAggregator eventAggregator) public QueueService(IEventAggregator eventAggregator,
IHistoryService historyService)
{ {
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_historyService = historyService;
} }
public List<Queue> GetQueue() public List<Queue> GetQueue()
@ -65,6 +69,13 @@ namespace NzbDrone.Core.Queue
private Queue MapAlbum(TrackedDownload trackedDownload, Album album) private Queue MapAlbum(TrackedDownload trackedDownload, Album album)
{ {
bool downloadForced = false;
var history = _historyService.Find(trackedDownload.DownloadItem.DownloadId, HistoryEventType.Grabbed).FirstOrDefault();
if (history != null && history.Data.ContainsKey("downloadForced"))
{
downloadForced = bool.Parse(history.Data["downloadForced"]);
}
var queue = new Queue var queue = new Queue
{ {
Id = HashConverter.GetHashInt31(string.Format("trackedDownload-{0}-album{1}", trackedDownload.DownloadItem.DownloadId, album.Id)), Id = HashConverter.GetHashInt31(string.Format("trackedDownload-{0}-album{1}", trackedDownload.DownloadItem.DownloadId, album.Id)),
@ -83,7 +94,8 @@ namespace NzbDrone.Core.Queue
DownloadId = trackedDownload.DownloadItem.DownloadId, DownloadId = trackedDownload.DownloadItem.DownloadId,
Protocol = trackedDownload.Protocol, Protocol = trackedDownload.Protocol,
DownloadClient = trackedDownload.DownloadItem.DownloadClient, DownloadClient = trackedDownload.DownloadItem.DownloadClient,
Indexer = trackedDownload.Indexer Indexer = trackedDownload.Indexer,
DownloadForced = downloadForced
}; };
if (queue.Timeleft.HasValue) if (queue.Timeleft.HasValue)

Loading…
Cancel
Save