mirror of
https://github.com/Sonarr/Sonarr.git
synced 2025-01-25 11:13:39 +02:00
New: Ability to forcibly grab a release from Interactive Search
Closes #395
This commit is contained in:
parent
70fb1551af
commit
8aecec507e
@ -90,6 +90,7 @@ const columns = [
|
||||
|
||||
function InteractiveSearch(props) {
|
||||
const {
|
||||
searchPayload,
|
||||
isFetching,
|
||||
isPopulated,
|
||||
error,
|
||||
@ -164,6 +165,7 @@ function InteractiveSearch(props) {
|
||||
<InteractiveSearchRow
|
||||
key={item.guid}
|
||||
{...item}
|
||||
searchPayload={searchPayload}
|
||||
longDateFormat={longDateFormat}
|
||||
timeFormat={timeFormat}
|
||||
onGrabPress={onGrabPress}
|
||||
@ -186,6 +188,7 @@ function InteractiveSearch(props) {
|
||||
}
|
||||
|
||||
InteractiveSearch.propTypes = {
|
||||
searchPayload: PropTypes.object.isRequired,
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
isPopulated: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
|
@ -41,8 +41,8 @@ function createMapDispatchToProps(dispatch, props) {
|
||||
dispatch(action({ selectedFilterKey }));
|
||||
},
|
||||
|
||||
onGrabPress(guid, indexerId) {
|
||||
dispatch(releaseActions.grabRelease({ guid, indexerId }));
|
||||
onGrabPress(payload) {
|
||||
dispatch(releaseActions.grabRelease(payload));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||
import Icon from 'Components/Icon';
|
||||
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
|
||||
import Link from 'Components/Link/Link';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
@ -42,6 +43,17 @@ function getDownloadTooltip(isGrabbing, isGrabbed, grabError) {
|
||||
|
||||
class InteractiveSearchRow extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
isConfirmGrabModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
@ -50,9 +62,37 @@ class InteractiveSearchRow extends Component {
|
||||
guid,
|
||||
indexerId,
|
||||
onGrabPress
|
||||
}= this.props;
|
||||
} = this.props;
|
||||
|
||||
onGrabPress(guid, indexerId);
|
||||
onGrabPress({
|
||||
guid,
|
||||
indexerId
|
||||
});
|
||||
}
|
||||
|
||||
onConfirmGrabPress = () => {
|
||||
this.setState({ isConfirmGrabModalOpen: true });
|
||||
}
|
||||
|
||||
onGrabConfirm = () => {
|
||||
this.setState({ isConfirmGrabModalOpen: false });
|
||||
|
||||
const {
|
||||
guid,
|
||||
indexerId,
|
||||
searchPayload,
|
||||
onGrabPress
|
||||
} = this.props;
|
||||
|
||||
onGrabPress({
|
||||
guid,
|
||||
indexerId,
|
||||
...searchPayload
|
||||
});
|
||||
}
|
||||
|
||||
onGrabCancel = () => {
|
||||
this.setState({ isConfirmGrabModalOpen: false });
|
||||
}
|
||||
|
||||
//
|
||||
@ -165,17 +205,24 @@ class InteractiveSearchRow extends Component {
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.download}>
|
||||
{
|
||||
downloadAllowed &&
|
||||
<SpinnerIconButton
|
||||
name={getDownloadIcon(isGrabbing, isGrabbed, grabError)}
|
||||
kind={grabError ? kinds.DANGER : kinds.DEFAULT}
|
||||
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
|
||||
isSpinning={isGrabbing}
|
||||
onPress={this.onGrabPress}
|
||||
/>
|
||||
}
|
||||
<SpinnerIconButton
|
||||
name={getDownloadIcon(isGrabbing, isGrabbed, grabError)}
|
||||
kind={grabError ? kinds.DANGER : kinds.DEFAULT}
|
||||
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
|
||||
isSpinning={isGrabbing}
|
||||
onPress={downloadAllowed ? this.onGrabPress : this.onConfirmGrabPress}
|
||||
/>
|
||||
</TableRowCell>
|
||||
|
||||
<ConfirmModal
|
||||
isOpen={this.state.isConfirmGrabModalOpen}
|
||||
kind={kinds.WARNING}
|
||||
title="Grab Release"
|
||||
message={`Sonarr was unable to determine which series and episode this release was for. Sonarr may be unable to automatically import this release. Do you want to grab '${title}'?`}
|
||||
confirmLabel="Grab"
|
||||
onConfirm={this.onGrabConfirm}
|
||||
onCancel={this.onGrabCancel}
|
||||
/>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
@ -205,6 +252,7 @@ InteractiveSearchRow.propTypes = {
|
||||
grabError: PropTypes.string,
|
||||
longDateFormat: PropTypes.string.isRequired,
|
||||
timeFormat: PropTypes.string.isRequired,
|
||||
searchPayload: PropTypes.object.isRequired,
|
||||
onGrabPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
@ -5,12 +5,15 @@ using Nancy;
|
||||
using Nancy.ModelBinding;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Exceptions;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.IndexerSearch;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Validation;
|
||||
using Sonarr.Http.Extensions;
|
||||
using HttpStatusCode = System.Net.HttpStatusCode;
|
||||
@ -24,6 +27,9 @@ namespace Sonarr.Api.V3.Indexers
|
||||
private readonly IMakeDownloadDecision _downloadDecisionMaker;
|
||||
private readonly IPrioritizeDownloadDecision _prioritizeDownloadDecision;
|
||||
private readonly IDownloadService _downloadService;
|
||||
private readonly ISeriesService _seriesService;
|
||||
private readonly IEpisodeService _episodeService;
|
||||
private readonly IParsingService _parsingService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
private readonly ICached<RemoteEpisode> _remoteEpisodeCache;
|
||||
@ -33,6 +39,9 @@ namespace Sonarr.Api.V3.Indexers
|
||||
IMakeDownloadDecision downloadDecisionMaker,
|
||||
IPrioritizeDownloadDecision prioritizeDownloadDecision,
|
||||
IDownloadService downloadService,
|
||||
ISeriesService seriesService,
|
||||
IEpisodeService episodeService,
|
||||
IParsingService parsingService,
|
||||
ICacheManager cacheManager,
|
||||
Logger logger)
|
||||
{
|
||||
@ -41,6 +50,9 @@ namespace Sonarr.Api.V3.Indexers
|
||||
_downloadDecisionMaker = downloadDecisionMaker;
|
||||
_prioritizeDownloadDecision = prioritizeDownloadDecision;
|
||||
_downloadService = downloadService;
|
||||
_seriesService = seriesService;
|
||||
_episodeService = episodeService;
|
||||
_parsingService = parsingService;
|
||||
_logger = logger;
|
||||
|
||||
GetResourceAll = GetReleases;
|
||||
@ -66,6 +78,34 @@ namespace Sonarr.Api.V3.Indexers
|
||||
|
||||
try
|
||||
{
|
||||
if (remoteEpisode.Series == null)
|
||||
{
|
||||
if (release.EpisodeId.HasValue)
|
||||
{
|
||||
var episode = _episodeService.GetEpisode(release.EpisodeId.Value);
|
||||
|
||||
remoteEpisode.Series = _seriesService.GetSeries(episode.SeriesId);
|
||||
remoteEpisode.Episodes = new List<Episode> { episode };
|
||||
}
|
||||
else if (release.SeriesId.HasValue)
|
||||
{
|
||||
var series = _seriesService.GetSeries(release.SeriesId.Value);
|
||||
var episodes = _parsingService.GetEpisodes(remoteEpisode.ParsedEpisodeInfo, series, true);
|
||||
|
||||
if (episodes.Empty())
|
||||
{
|
||||
throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to parse episodes in the release");
|
||||
}
|
||||
|
||||
remoteEpisode.Series = series;
|
||||
remoteEpisode.Episodes = episodes;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NzbDroneClientException(HttpStatusCode.NotFound, "Unable to find matching series and episodes");
|
||||
}
|
||||
}
|
||||
|
||||
_downloadService.DownloadReport(remoteEpisode);
|
||||
}
|
||||
catch (ReleaseDownloadException ex)
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Languages;
|
||||
@ -61,6 +62,16 @@ namespace Sonarr.Api.V3.Indexers
|
||||
public bool IsAbsoluteNumbering { get; set; }
|
||||
public bool IsPossibleSpecialEpisode { get; set; }
|
||||
public bool Special { get; set; }
|
||||
|
||||
// Sent when queuing an unknown release
|
||||
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
// [JsonIgnore]
|
||||
public int? SeriesId { get; set; }
|
||||
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
// [JsonIgnore]
|
||||
public int? EpisodeId { get; set; }
|
||||
}
|
||||
|
||||
public static class ReleaseResourceMapper
|
||||
|
Loading…
x
Reference in New Issue
Block a user