parent
c871b3f948
commit
f30ae69c10
|
@ -6,7 +6,8 @@ import {
|
||||||
updateInteractiveImportItem,
|
updateInteractiveImportItem,
|
||||||
fetchInteractiveImportEpisodes,
|
fetchInteractiveImportEpisodes,
|
||||||
setInteractiveImportEpisodesSort,
|
setInteractiveImportEpisodesSort,
|
||||||
clearInteractiveImportEpisodes
|
clearInteractiveImportEpisodes,
|
||||||
|
reprocessInteractiveImportItems
|
||||||
} from 'Store/Actions/interactiveImportActions';
|
} from 'Store/Actions/interactiveImportActions';
|
||||||
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
|
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
|
||||||
import SelectEpisodeModalContent from './SelectEpisodeModalContent';
|
import SelectEpisodeModalContent from './SelectEpisodeModalContent';
|
||||||
|
@ -21,10 +22,11 @@ function createMapStateToProps() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
fetchInteractiveImportEpisodes,
|
dispatchFetchInteractiveImportEpisodes: fetchInteractiveImportEpisodes,
|
||||||
setInteractiveImportEpisodesSort,
|
dispatchSetInteractiveImportEpisodesSort: setInteractiveImportEpisodesSort,
|
||||||
clearInteractiveImportEpisodes,
|
dispatchClearInteractiveImportEpisodes: clearInteractiveImportEpisodes,
|
||||||
updateInteractiveImportItem
|
dispatchUpdateInteractiveImportItem: updateInteractiveImportItem,
|
||||||
|
dispatchReprocessInteractiveImportItems: reprocessInteractiveImportItems
|
||||||
};
|
};
|
||||||
|
|
||||||
class SelectEpisodeModalContentConnector extends Component {
|
class SelectEpisodeModalContentConnector extends Component {
|
||||||
|
@ -38,26 +40,28 @@ class SelectEpisodeModalContentConnector extends Component {
|
||||||
seasonNumber
|
seasonNumber
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
this.props.fetchInteractiveImportEpisodes({ seriesId, seasonNumber });
|
this.props.dispatchFetchInteractiveImportEpisodes({ seriesId, seasonNumber });
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
// This clears the episodes for the queue and hides the queue
|
// This clears the episodes for the queue and hides the queue
|
||||||
// We'll need another place to store episodes for manual import
|
// We'll need another place to store episodes for manual import
|
||||||
this.props.clearInteractiveImportEpisodes();
|
this.props.dispatchClearInteractiveImportEpisodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onSortPress = (sortKey, sortDirection) => {
|
onSortPress = (sortKey, sortDirection) => {
|
||||||
this.props.setInteractiveImportEpisodesSort({ sortKey, sortDirection });
|
this.props.dispatchSetInteractiveImportEpisodesSort({ sortKey, sortDirection });
|
||||||
}
|
}
|
||||||
|
|
||||||
onEpisodesSelect = (episodeIds) => {
|
onEpisodesSelect = (episodeIds) => {
|
||||||
const {
|
const {
|
||||||
ids,
|
ids,
|
||||||
items,
|
items,
|
||||||
|
dispatchUpdateInteractiveImportItem,
|
||||||
|
dispatchReprocessInteractiveImportItems,
|
||||||
onModalClose
|
onModalClose
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -78,12 +82,14 @@ class SelectEpisodeModalContentConnector extends Component {
|
||||||
const startingIndex = index * episodesPerFile;
|
const startingIndex = index * episodesPerFile;
|
||||||
const episodes = sortedEpisodes.slice(startingIndex, startingIndex + episodesPerFile);
|
const episodes = sortedEpisodes.slice(startingIndex, startingIndex + episodesPerFile);
|
||||||
|
|
||||||
this.props.updateInteractiveImportItem({
|
dispatchUpdateInteractiveImportItem({
|
||||||
id,
|
id,
|
||||||
episodes
|
episodes
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dispatchReprocessInteractiveImportItems({ ids });
|
||||||
|
|
||||||
onModalClose(true);
|
onModalClose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,10 +112,11 @@ SelectEpisodeModalContentConnector.propTypes = {
|
||||||
seriesId: PropTypes.number.isRequired,
|
seriesId: PropTypes.number.isRequired,
|
||||||
seasonNumber: PropTypes.number.isRequired,
|
seasonNumber: PropTypes.number.isRequired,
|
||||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
fetchInteractiveImportEpisodes: PropTypes.func.isRequired,
|
dispatchFetchInteractiveImportEpisodes: PropTypes.func.isRequired,
|
||||||
setInteractiveImportEpisodesSort: PropTypes.func.isRequired,
|
dispatchSetInteractiveImportEpisodesSort: PropTypes.func.isRequired,
|
||||||
clearInteractiveImportEpisodes: PropTypes.func.isRequired,
|
dispatchClearInteractiveImportEpisodes: PropTypes.func.isRequired,
|
||||||
updateInteractiveImportItem: PropTypes.func.isRequired,
|
dispatchUpdateInteractiveImportItem: PropTypes.func.isRequired,
|
||||||
|
dispatchReprocessInteractiveImportItems: PropTypes.func.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { fetchLanguageProfileSchema } from 'Store/Actions/settingsActions';
|
import { fetchLanguageProfileSchema } from 'Store/Actions/settingsActions';
|
||||||
import { updateInteractiveImportItems } from 'Store/Actions/interactiveImportActions';
|
import { updateInteractiveImportItems, reprocessInteractiveImportItems } from 'Store/Actions/interactiveImportActions';
|
||||||
import SelectLanguageModalContent from './SelectLanguageModalContent';
|
import SelectLanguageModalContent from './SelectLanguageModalContent';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
|
@ -30,7 +30,8 @@ function createMapStateToProps() {
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
dispatchFetchLanguageProfileSchema: fetchLanguageProfileSchema,
|
dispatchFetchLanguageProfileSchema: fetchLanguageProfileSchema,
|
||||||
dispatchUpdateInteractiveImportItems: updateInteractiveImportItems
|
dispatchUpdateInteractiveImportItems: updateInteractiveImportItems,
|
||||||
|
dispatchReprocessInteractiveImportItems: reprocessInteractiveImportItems
|
||||||
};
|
};
|
||||||
|
|
||||||
class SelectLanguageModalContentConnector extends Component {
|
class SelectLanguageModalContentConnector extends Component {
|
||||||
|
@ -48,15 +49,23 @@ class SelectLanguageModalContentConnector extends Component {
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onLanguageSelect = ({ value }) => {
|
onLanguageSelect = ({ value }) => {
|
||||||
|
const {
|
||||||
|
ids,
|
||||||
|
dispatchUpdateInteractiveImportItems,
|
||||||
|
dispatchReprocessInteractiveImportItems
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
const languageId = parseInt(value);
|
const languageId = parseInt(value);
|
||||||
const language = _.find(this.props.items,
|
const language = _.find(this.props.items,
|
||||||
(item) => item.language.id === languageId).language;
|
(item) => item.language.id === languageId).language;
|
||||||
|
|
||||||
this.props.dispatchUpdateInteractiveImportItems({
|
dispatchUpdateInteractiveImportItems({
|
||||||
ids: this.props.ids,
|
ids,
|
||||||
language
|
language
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dispatchReprocessInteractiveImportItems({ ids });
|
||||||
|
|
||||||
this.props.onModalClose(true);
|
this.props.onModalClose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +90,7 @@ SelectLanguageModalContentConnector.propTypes = {
|
||||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
dispatchFetchLanguageProfileSchema: PropTypes.func.isRequired,
|
dispatchFetchLanguageProfileSchema: PropTypes.func.isRequired,
|
||||||
dispatchUpdateInteractiveImportItems: PropTypes.func.isRequired,
|
dispatchUpdateInteractiveImportItems: PropTypes.func.isRequired,
|
||||||
|
dispatchReprocessInteractiveImportItems: PropTypes.func.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import getQualities from 'Utilities/Quality/getQualities';
|
import getQualities from 'Utilities/Quality/getQualities';
|
||||||
import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions';
|
import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions';
|
||||||
import { updateInteractiveImportItems } from 'Store/Actions/interactiveImportActions';
|
import { updateInteractiveImportItems, reprocessInteractiveImportItems } from 'Store/Actions/interactiveImportActions';
|
||||||
import SelectQualityModalContent from './SelectQualityModalContent';
|
import SelectQualityModalContent from './SelectQualityModalContent';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
|
@ -31,7 +31,8 @@ function createMapStateToProps() {
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
dispatchFetchQualityProfileSchema: fetchQualityProfileSchema,
|
dispatchFetchQualityProfileSchema: fetchQualityProfileSchema,
|
||||||
dispatchUpdateInteractiveImportItems: updateInteractiveImportItems
|
dispatchUpdateInteractiveImportItems: updateInteractiveImportItems,
|
||||||
|
dispatchReprocessInteractiveImportItems: reprocessInteractiveImportItems
|
||||||
};
|
};
|
||||||
|
|
||||||
class SelectQualityModalContentConnector extends Component {
|
class SelectQualityModalContentConnector extends Component {
|
||||||
|
@ -49,6 +50,12 @@ class SelectQualityModalContentConnector extends Component {
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onQualitySelect = ({ qualityId, proper, real }) => {
|
onQualitySelect = ({ qualityId, proper, real }) => {
|
||||||
|
const {
|
||||||
|
ids,
|
||||||
|
dispatchUpdateInteractiveImportItems,
|
||||||
|
dispatchReprocessInteractiveImportItems
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
const quality = _.find(this.props.items,
|
const quality = _.find(this.props.items,
|
||||||
(item) => item.id === qualityId);
|
(item) => item.id === qualityId);
|
||||||
|
|
||||||
|
@ -57,14 +64,16 @@ class SelectQualityModalContentConnector extends Component {
|
||||||
real: real ? 1 : 0
|
real: real ? 1 : 0
|
||||||
};
|
};
|
||||||
|
|
||||||
this.props.dispatchUpdateInteractiveImportItems({
|
dispatchUpdateInteractiveImportItems({
|
||||||
ids: this.props.ids,
|
ids,
|
||||||
quality: {
|
quality: {
|
||||||
quality,
|
quality,
|
||||||
revision
|
revision
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dispatchReprocessInteractiveImportItems({ ids });
|
||||||
|
|
||||||
this.props.onModalClose(true);
|
this.props.onModalClose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +98,7 @@ SelectQualityModalContentConnector.propTypes = {
|
||||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
dispatchFetchQualityProfileSchema: PropTypes.func.isRequired,
|
dispatchFetchQualityProfileSchema: PropTypes.func.isRequired,
|
||||||
dispatchUpdateInteractiveImportItems: PropTypes.func.isRequired,
|
dispatchUpdateInteractiveImportItems: PropTypes.func.isRequired,
|
||||||
|
dispatchReprocessInteractiveImportItems: PropTypes.func.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -169,6 +169,10 @@ export const actionHandlers = handleThunks({
|
||||||
id,
|
id,
|
||||||
path: item.path,
|
path: item.path,
|
||||||
seriesId: item.series.id,
|
seriesId: item.series.id,
|
||||||
|
season: item.season,
|
||||||
|
episodeIds: item.episodes.map((e) => e.id),
|
||||||
|
quality: item.quality,
|
||||||
|
language: item.language,
|
||||||
downloadId: item.downloadId
|
downloadId: item.downloadId
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series);
|
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series);
|
||||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, DownloadClientItem downloadClientItem, ParsedEpisodeInfo folderInfo, bool sceneSource);
|
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, DownloadClientItem downloadClientItem, ParsedEpisodeInfo folderInfo, bool sceneSource);
|
||||||
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, DownloadClientItem downloadClientItem, ParsedEpisodeInfo folderInfo, bool sceneSource, bool filterExistingFiles);
|
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, DownloadClientItem downloadClientItem, ParsedEpisodeInfo folderInfo, bool sceneSource, bool filterExistingFiles);
|
||||||
|
ImportDecision GetDecision(LocalEpisode localEpisode, DownloadClientItem downloadClientItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportDecisionMaker : IMakeImportDecision
|
public class ImportDecisionMaker : IMakeImportDecision
|
||||||
|
@ -90,6 +91,14 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
return decisions;
|
return decisions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImportDecision GetDecision(LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
|
||||||
|
{
|
||||||
|
var reasons = _specifications.Select(c => EvaluateSpec(c, localEpisode, downloadClientItem))
|
||||||
|
.Where(c => c != null);
|
||||||
|
|
||||||
|
return new ImportDecision(localEpisode, reasons.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
private ImportDecision GetDecision(LocalEpisode localEpisode, DownloadClientItem downloadClientItem, bool otherFiles)
|
private ImportDecision GetDecision(LocalEpisode localEpisode, DownloadClientItem downloadClientItem, bool otherFiles)
|
||||||
{
|
{
|
||||||
ImportDecision decision = null;
|
ImportDecision decision = null;
|
||||||
|
@ -150,14 +159,6 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
return decision;
|
return decision;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImportDecision GetDecision(LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
|
|
||||||
{
|
|
||||||
var reasons = _specifications.Select(c => EvaluateSpec(c, localEpisode, downloadClientItem))
|
|
||||||
.Where(c => c != null);
|
|
||||||
|
|
||||||
return new ImportDecision(localEpisode, reasons.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Rejection EvaluateSpec(IImportDecisionEngineSpecification spec, LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
|
private Rejection EvaluateSpec(IImportDecisionEngineSpecification spec, LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -9,11 +9,13 @@ using NzbDrone.Common.Instrumentation.Extensions;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Download.TrackedDownloads;
|
using NzbDrone.Core.Download.TrackedDownloads;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation;
|
using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||||
|
@ -21,7 +23,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||||
public interface IManualImportService
|
public interface IManualImportService
|
||||||
{
|
{
|
||||||
List<ManualImportItem> GetMediaFiles(string path, string downloadId, int? seriesId, bool filterExistingFiles);
|
List<ManualImportItem> GetMediaFiles(string path, string downloadId, int? seriesId, bool filterExistingFiles);
|
||||||
ManualImportItem ReprocessItem(string path, string downloadId, int seriesId);
|
ManualImportItem ReprocessItem(string path, string downloadId, int seriesId, List<int> episodeIds, QualityModel quality, Language language);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ManualImportService : IExecute<ManualImportCommand>, IManualImportService
|
public class ManualImportService : IExecute<ManualImportCommand>, IManualImportService
|
||||||
|
@ -94,11 +96,32 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||||
return ProcessFolder(path, path, downloadId, seriesId, filterExistingFiles);
|
return ProcessFolder(path, path, downloadId, seriesId, filterExistingFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ManualImportItem ReprocessItem(string path, string downloadId, int seriesId)
|
public ManualImportItem ReprocessItem(string path, string downloadId, int seriesId, List<int> episodeIds, QualityModel quality, Language language)
|
||||||
{
|
{
|
||||||
var rootFolder = Path.GetDirectoryName(path);
|
var rootFolder = Path.GetDirectoryName(path);
|
||||||
var series = _seriesService.GetSeries(seriesId);
|
var series = _seriesService.GetSeries(seriesId);
|
||||||
|
|
||||||
|
if (episodeIds.Any())
|
||||||
|
{
|
||||||
|
var downloadClientItem = GetTrackedDownload(downloadId)?.DownloadItem;
|
||||||
|
|
||||||
|
var localEpisode = new LocalEpisode
|
||||||
|
{
|
||||||
|
Series = series,
|
||||||
|
Episodes = _episodeService.GetEpisodes(episodeIds),
|
||||||
|
FileEpisodeInfo = Parser.Parser.ParsePath(path),
|
||||||
|
DownloadClientEpisodeInfo = downloadClientItem == null ? null : Parser.Parser.ParseTitle(downloadClientItem.Title),
|
||||||
|
Path = path,
|
||||||
|
SceneSource = SceneSource(series, rootFolder),
|
||||||
|
ExistingFile = series.Path.IsParentPath(path),
|
||||||
|
Size = _diskProvider.GetFileSize(path),
|
||||||
|
Language = language,
|
||||||
|
Quality = quality
|
||||||
|
};
|
||||||
|
|
||||||
|
return MapItem(_importDecisionMaker.GetDecision(localEpisode, downloadClientItem), rootFolder, downloadId, null);
|
||||||
|
}
|
||||||
|
|
||||||
return ProcessFile(rootFolder, rootFolder, path, downloadId, series);
|
return ProcessFile(rootFolder, rootFolder, path, downloadId, series);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +185,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DownloadClientItem downloadClientItem = null;
|
var trackedDownload = GetTrackedDownload(downloadId);
|
||||||
var relativeFile = baseFolder.GetRelativePath(file);
|
var relativeFile = baseFolder.GetRelativePath(file);
|
||||||
|
|
||||||
if (series == null)
|
if (series == null)
|
||||||
|
@ -175,15 +198,9 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||||
series = _parsingService.GetSeries(relativeFile);
|
series = _parsingService.GetSeries(relativeFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downloadId.IsNotNullOrWhiteSpace())
|
if (trackedDownload != null && series == null)
|
||||||
{
|
{
|
||||||
var trackedDownload = _trackedDownloadService.Find(downloadId);
|
series = trackedDownload?.RemoteEpisode?.Series;
|
||||||
downloadClientItem = trackedDownload?.DownloadItem;
|
|
||||||
|
|
||||||
if (series == null)
|
|
||||||
{
|
|
||||||
series = trackedDownload?.RemoteEpisode?.Series;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series == null)
|
if (series == null)
|
||||||
|
@ -209,7 +226,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||||
}
|
}
|
||||||
|
|
||||||
var importDecisions = _importDecisionMaker.GetImportDecisions(new List<string> {file}, series,
|
var importDecisions = _importDecisionMaker.GetImportDecisions(new List<string> {file}, series,
|
||||||
downloadClientItem, null, SceneSource(series, baseFolder));
|
trackedDownload?.DownloadItem, null, SceneSource(series, baseFolder));
|
||||||
|
|
||||||
if (importDecisions.Any())
|
if (importDecisions.Any())
|
||||||
{
|
{
|
||||||
|
@ -236,6 +253,18 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
|
||||||
return !(series.Path.PathEquals(folder) || series.Path.IsParentPath(folder));
|
return !(series.Path.PathEquals(folder) || series.Path.IsParentPath(folder));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TrackedDownload GetTrackedDownload(string downloadId)
|
||||||
|
{
|
||||||
|
if (downloadId.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
var trackedDownload = _trackedDownloadService.Find(downloadId);
|
||||||
|
|
||||||
|
return trackedDownload;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private ManualImportItem MapItem(ImportDecision decision, string rootFolder, string downloadId, string folderName)
|
private ManualImportItem MapItem(ImportDecision decision, string rootFolder, string downloadId, string folderName)
|
||||||
{
|
{
|
||||||
var item = new ManualImportItem();
|
var item = new ManualImportItem();
|
||||||
|
|
|
@ -38,11 +38,14 @@ namespace Sonarr.Api.V3.ManualImport
|
||||||
|
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
var processedItem = _manualImportService.ReprocessItem(item.Path, item.DownloadId, item.SeriesId);
|
var processedItem = _manualImportService.ReprocessItem(item.Path, item.DownloadId, item.SeriesId, item.EpisodeIds ?? new List<int>(), item.Quality, item.Language);
|
||||||
|
|
||||||
item.SeasonNumber = processedItem.SeasonNumber;
|
item.SeasonNumber = processedItem.SeasonNumber;
|
||||||
item.Episodes = processedItem.Episodes.ToResource();
|
item.Episodes = processedItem.Episodes.ToResource();
|
||||||
item.Rejections = processedItem.Rejections;
|
item.Rejections = processedItem.Rejections;
|
||||||
|
|
||||||
|
// Clear episode IDs in favour of the full episode
|
||||||
|
item.EpisodeIds = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using Sonarr.Api.V3.Episodes;
|
using Sonarr.Api.V3.Episodes;
|
||||||
using Sonarr.Http.REST;
|
using Sonarr.Http.REST;
|
||||||
|
|
||||||
|
@ -11,6 +13,9 @@ namespace Sonarr.Api.V3.ManualImport
|
||||||
public int SeriesId { get; set; }
|
public int SeriesId { get; set; }
|
||||||
public int? SeasonNumber { get; set; }
|
public int? SeasonNumber { get; set; }
|
||||||
public List<EpisodeResource> Episodes { get; set; }
|
public List<EpisodeResource> Episodes { get; set; }
|
||||||
|
public List<int> EpisodeIds { get; set; }
|
||||||
|
public QualityModel Quality { get; set; }
|
||||||
|
public Language Language { get; set; }
|
||||||
public string DownloadId { get; set; }
|
public string DownloadId { get; set; }
|
||||||
|
|
||||||
public IEnumerable<Rejection> Rejections { get; set; }
|
public IEnumerable<Rejection> Rejections { get; set; }
|
||||||
|
|
Loading…
Reference in New Issue