mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-16 10:03:51 -07:00
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
This commit is contained in:
parent
eedaa2a7b8
commit
c98b86b413
12 changed files with 62 additions and 17 deletions
|
@ -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,10 +156,9 @@ 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 ? kinds.DANGER : kinds.DEFAULT}
|
kind={grabError || !downloadAllowed ? kinds.DANGER : kinds.DEFAULT}
|
||||||
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
|
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
|
||||||
isSpinning={isGrabbing}
|
isSpinning={isGrabbing}
|
||||||
onPress={this.onGrabPress}
|
onPress={this.onGrabPress}
|
||||||
|
|
|
@ -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…
Add table
Add a link
Reference in a new issue