diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js
index 9203baf11..573a81f49 100644
--- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js
+++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js
@@ -19,6 +19,7 @@ import { align, icons, kinds, scrollDirections } from 'Helpers/Props';
import SelectLanguageModal from 'InteractiveImport/Language/SelectLanguageModal';
import SelectMovieModal from 'InteractiveImport/Movie/SelectMovieModal';
import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal';
+import SelectReleaseGroupModal from 'InteractiveImport/ReleaseGroup/SelectReleaseGroupModal';
import getErrorMessage from 'Utilities/Object/getErrorMessage';
import translate from 'Utilities/String/translate';
import getSelectedIds from 'Utilities/Table/getSelectedIds';
@@ -40,6 +41,11 @@ const columns = [
isSortable: true,
isVisible: true
},
+ {
+ name: 'releaseGroup',
+ label: translate('ReleaseGroup'),
+ isVisible: true
+ },
{
name: 'quality',
label: translate('Quality'),
@@ -83,6 +89,7 @@ const SELECT = 'select';
const MOVIE = 'movie';
const LANGUAGE = 'language';
const QUALITY = 'quality';
+const RELEASE_GROUP = 'releaseGroup';
class InteractiveImportModalContent extends Component {
@@ -202,10 +209,11 @@ class InteractiveImportModalContent extends Component {
const errorMessage = getErrorMessage(error, translate('UnableToLoadManualImportItems'));
const bulkSelectOptions = [
- {
- key: SELECT, value: translate('SelectDotDot'), disabled: true },
+ { key: SELECT, value: translate('SelectDotDot'), disabled: true },
{ key: LANGUAGE, value: translate('SelectLanguage') },
- { key: QUALITY, value: translate('SelectQuality') }];
+ { key: QUALITY, value: translate('SelectQuality') },
+ { key: RELEASE_GROUP, value: translate('SelectReleaseGroup') }
+ ];
if (allowMovieChange) {
bulkSelectOptions.splice(1, 0, {
@@ -372,6 +380,13 @@ class InteractiveImportModalContent extends Component {
real={false}
onModalClose={this.onSelectModalClose}
/>
+
+
);
}
diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js
index 75bedbc0d..4759814d8 100644
--- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js
+++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js
@@ -110,7 +110,8 @@ class InteractiveImportModalContentConnector extends Component {
const {
movie,
quality,
- languages
+ languages,
+ releaseGroup
} = item;
if (!movie) {
@@ -132,6 +133,7 @@ class InteractiveImportModalContentConnector extends Component {
path: item.path,
folderName: item.folderName,
movieId: movie.id,
+ releaseGroup,
quality,
languages,
downloadId: this.props.downloadId
diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js
index 19a340893..27f8caee0 100644
--- a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js
+++ b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js
@@ -11,6 +11,7 @@ import { icons, kinds, tooltipPositions } from 'Helpers/Props';
import SelectLanguageModal from 'InteractiveImport/Language/SelectLanguageModal';
import SelectMovieModal from 'InteractiveImport/Movie/SelectMovieModal';
import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal';
+import SelectReleaseGroupModal from 'InteractiveImport/ReleaseGroup/SelectReleaseGroupModal';
import MovieLanguage from 'Movie/MovieLanguage';
import MovieQuality from 'Movie/MovieQuality';
import formatBytes from 'Utilities/Number/formatBytes';
@@ -28,6 +29,7 @@ class InteractiveImportRow extends Component {
this.state = {
isSelectMovieModalOpen: false,
+ isSelectReleaseGroupModalOpen: false,
isSelectQualityModalOpen: false,
isSelectLanguageModalOpen: false
};
@@ -103,6 +105,10 @@ class InteractiveImportRow extends Component {
this.setState({ isSelectMovieModalOpen: true });
}
+ onSelectReleaseGroupPress = () => {
+ this.setState({ isSelectReleaseGroupModalOpen: true });
+ }
+
onSelectQualityPress = () => {
this.setState({ isSelectQualityModalOpen: true });
}
@@ -116,6 +122,11 @@ class InteractiveImportRow extends Component {
this.selectRowAfterChange(changed);
}
+ onSelectReleaseGroupModalClose = (changed) => {
+ this.setState({ isSelectReleaseGroupModalOpen: false });
+ this.selectRowAfterChange(changed);
+ }
+
onSelectQualityModalClose = (changed) => {
this.setState({ isSelectQualityModalOpen: false });
this.selectRowAfterChange(changed);
@@ -137,6 +148,7 @@ class InteractiveImportRow extends Component {
movie,
quality,
languages,
+ releaseGroup,
size,
rejections,
isReprocessing,
@@ -147,7 +159,8 @@ class InteractiveImportRow extends Component {
const {
isSelectMovieModalOpen,
isSelectQualityModalOpen,
- isSelectLanguageModalOpen
+ isSelectLanguageModalOpen,
+ isSelectReleaseGroupModalOpen
} = this.state;
const movieTitle = movie ? movie.title + ( movie.year > 0 ? ` (${movie.year})` : '') : '';
@@ -155,6 +168,7 @@ class InteractiveImportRow extends Component {
const showMoviePlaceholder = isSelected && !movie;
const showQualityPlaceholder = isSelected && !quality;
const showLanguagePlaceholder = isSelected && !languages && !isReprocessing;
+ const showReleaseGroupPlaceholder = isSelected && !releaseGroup;
return (
@@ -181,6 +195,17 @@ class InteractiveImportRow extends Component {
}
+
+ {
+ showReleaseGroupPlaceholder ?
+ :
+ releaseGroup
+ }
+
+
+
+
+
+
+ );
+ }
+}
+
+SelectReleaseGroupModal.propTypes = {
+ isOpen: PropTypes.bool.isRequired,
+ onModalClose: PropTypes.func.isRequired
+};
+
+export default SelectReleaseGroupModal;
diff --git a/frontend/src/InteractiveImport/ReleaseGroup/SelectReleaseGroupModalContent.js b/frontend/src/InteractiveImport/ReleaseGroup/SelectReleaseGroupModalContent.js
new file mode 100644
index 000000000..549abc22e
--- /dev/null
+++ b/frontend/src/InteractiveImport/ReleaseGroup/SelectReleaseGroupModalContent.js
@@ -0,0 +1,99 @@
+import PropTypes from 'prop-types';
+import React, { Component } from 'react';
+import Form from 'Components/Form/Form';
+import FormGroup from 'Components/Form/FormGroup';
+import FormInputGroup from 'Components/Form/FormInputGroup';
+import FormLabel from 'Components/Form/FormLabel';
+import Button from 'Components/Link/Button';
+import ModalBody from 'Components/Modal/ModalBody';
+import ModalContent from 'Components/Modal/ModalContent';
+import ModalFooter from 'Components/Modal/ModalFooter';
+import ModalHeader from 'Components/Modal/ModalHeader';
+import { inputTypes, kinds } from 'Helpers/Props';
+import translate from 'Utilities/String/translate';
+
+class SelectReleaseGroupModalContent extends Component {
+
+ //
+ // Lifecycle
+
+ constructor(props, context) {
+ super(props, context);
+
+ const {
+ releaseGroup
+ } = props;
+
+ this.state = {
+ releaseGroup
+ };
+ }
+
+ //
+ // Listeners
+
+ onReleaseGroupChange = ({ value }) => {
+ this.setState({ releaseGroup: value });
+ }
+
+ onReleaseGroupSelect = () => {
+ this.props.onReleaseGroupSelect(this.state);
+ }
+
+ //
+ // Render
+
+ render() {
+ const {
+ onModalClose
+ } = this.props;
+
+ const {
+ releaseGroup
+ } = this.state;
+
+ return (
+
+
+ {translate('ManualImportSetReleaseGroup')}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+SelectReleaseGroupModalContent.propTypes = {
+ releaseGroup: PropTypes.string.isRequired,
+ onReleaseGroupSelect: PropTypes.func.isRequired,
+ onModalClose: PropTypes.func.isRequired
+};
+
+export default SelectReleaseGroupModalContent;
diff --git a/frontend/src/InteractiveImport/ReleaseGroup/SelectReleaseGroupModalContentConnector.js b/frontend/src/InteractiveImport/ReleaseGroup/SelectReleaseGroupModalContentConnector.js
new file mode 100644
index 000000000..1dba63894
--- /dev/null
+++ b/frontend/src/InteractiveImport/ReleaseGroup/SelectReleaseGroupModalContentConnector.js
@@ -0,0 +1,54 @@
+import PropTypes from 'prop-types';
+import React, { Component } from 'react';
+import { connect } from 'react-redux';
+import { reprocessInteractiveImportItems, updateInteractiveImportItems } from 'Store/Actions/interactiveImportActions';
+import SelectReleaseGroupModalContent from './SelectReleaseGroupModalContent';
+
+const mapDispatchToProps = {
+ dispatchUpdateInteractiveImportItems: updateInteractiveImportItems,
+ dispatchReprocessInteractiveImportItems: reprocessInteractiveImportItems
+};
+
+class SelectReleaseGroupModalContentConnector extends Component {
+
+ //
+ // Listeners
+
+ onReleaseGroupSelect = ({ releaseGroup }) => {
+ const {
+ ids,
+ dispatchUpdateInteractiveImportItems,
+ dispatchReprocessInteractiveImportItems
+ } = this.props;
+
+ dispatchUpdateInteractiveImportItems({
+ ids,
+ releaseGroup
+ });
+
+ dispatchReprocessInteractiveImportItems({ ids });
+
+ this.props.onModalClose(true);
+ }
+
+ //
+ // Render
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+SelectReleaseGroupModalContentConnector.propTypes = {
+ ids: PropTypes.arrayOf(PropTypes.number).isRequired,
+ dispatchUpdateInteractiveImportItems: PropTypes.func.isRequired,
+ dispatchReprocessInteractiveImportItems: PropTypes.func.isRequired,
+ onModalClose: PropTypes.func.isRequired
+};
+
+export default connect(null, mapDispatchToProps)(SelectReleaseGroupModalContentConnector);
diff --git a/frontend/src/Store/Actions/interactiveImportActions.js b/frontend/src/Store/Actions/interactiveImportActions.js
index 491c77fd4..55b91d1d6 100644
--- a/frontend/src/Store/Actions/interactiveImportActions.js
+++ b/frontend/src/Store/Actions/interactiveImportActions.js
@@ -148,9 +148,10 @@ export const actionHandlers = handleThunks({
return {
id,
path: item.path,
- movieId: item.movie.id,
+ movieId: item.movie ? item.movie.id : undefined,
quality: item.quality,
languages: item.languages,
+ releaseGroup: item.releaseGroup,
downloadId: item.downloadId
};
});
diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json
index 367e6ea2d..d0d2e5e58 100644
--- a/src/NzbDrone.Core/Localization/Core/en.json
+++ b/src/NzbDrone.Core/Localization/Core/en.json
@@ -128,6 +128,7 @@
"ClickToChangeLanguage": "Click to change language",
"ClickToChangeMovie": "Click to change movie",
"ClickToChangeQuality": "Click to change quality",
+ "ClickToChangeReleaseGroup": "Click to change release group",
"ClientPriority": "Client Priority",
"CloneCustomFormat": "Clone Custom Format",
"CloneFormatTag": "Clone Format Tag",
@@ -491,6 +492,7 @@
"ManualImportSelectLanguage": "Manual Import - Select Language",
"ManualImportSelectMovie": "Manual Import - Select Movie",
"ManualImportSelectQuality": " Manual Import - Select Quality",
+ "ManualImportSetReleaseGroup": "Manual Import - Set Release Group",
"MappedDrivesRunningAsService": "Mapped network drives are not available when running as a Windows Service. Please see the FAQ for more information",
"MarkAsFailed": "Mark as Failed",
"MarkAsFailedMessageText": "Are you sure you want to mark '{0}' as failed?",
@@ -881,6 +883,7 @@
"SelectLanguges": "Select Languages",
"SelectMovie": "Select Movie",
"SelectQuality": "Select Quality",
+ "SelectReleaseGroup": "Select Release Group",
"SendAnonymousUsageData": "Send Anonymous Usage Data",
"SetPermissions": "Set Permissions",
"SetPermissionsLinuxHelpText": "Should chmod be run when files are imported/renamed?",
diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguage.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguage.cs
index 3df7c2f0a..60cadfcfe 100644
--- a/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguage.cs
+++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Aggregation/Aggregators/AggregateLanguage.cs
@@ -22,7 +22,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Aggregation.Aggregators
public LocalMovie Aggregate(LocalMovie localMovie, DownloadClientItem downloadClientItem, bool otherFiles)
{
- var languages = new List { localMovie.Movie.OriginalLanguage ?? Language.Unknown };
+ var languages = new List { localMovie.Movie?.OriginalLanguage ?? Language.Unknown };
var languagesConfidence = Confidence.Default;
foreach (var augmentLanguage in _augmentLanguages)
diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportFile.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportFile.cs
index 0aab4af3f..87c500de1 100644
--- a/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportFile.cs
+++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportFile.cs
@@ -12,6 +12,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
public string FolderName { get; set; }
public QualityModel Quality { get; set; }
public List Languages { get; set; }
+ public string ReleaseGroup { get; set; }
public string DownloadId { get; set; }
public int MovieId { get; set; }
diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportItem.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportItem.cs
index 613cc6ca7..6ed20c180 100644
--- a/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportItem.cs
+++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportItem.cs
@@ -15,6 +15,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
public long Size { get; set; }
public QualityModel Quality { get; set; }
public List Languages { get; set; }
+ public string ReleaseGroup { get; set; }
public string DownloadId { get; set; }
public IEnumerable Rejections { get; set; }
public Movie Movie { get; set; }
diff --git a/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs b/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs
index c2909c7c7..e3099bd5f 100644
--- a/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs
+++ b/src/NzbDrone.Core/MediaFiles/MovieImport/Manual/ManualImportService.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -22,7 +23,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
public interface IManualImportService
{
List GetMediaFiles(string path, string downloadId, int? movieId, bool filterExistingFiles);
- ManualImportItem ReprocessItem(string path, string downloadId, int movieId, QualityModel quality, List languages);
+ ManualImportItem ReprocessItem(string path, string downloadId, int movieId, string releaseGroup, QualityModel quality, List languages);
}
public class ManualImportService : IExecute, IManualImportService
@@ -92,13 +93,21 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
return ProcessFolder(path, path, downloadId, movieId, filterExistingFiles);
}
- public ManualImportItem ReprocessItem(string path, string downloadId, int movieId, QualityModel quality, List languages)
+ public ManualImportItem ReprocessItem(string path, string downloadId, int movieId, string releaseGroup, QualityModel quality, List languages)
{
var rootFolder = Path.GetDirectoryName(path);
var movie = _movieService.GetMovie(movieId);
var downloadClientItem = GetTrackedDownload(downloadId)?.DownloadItem;
+ var languageParse = LanguageParser.ParseLanguages(path);
+
+ if (languageParse.Count <= 1 && languageParse.First() == Language.Unknown && movie != null)
+ {
+ languageParse = new List { movie.OriginalLanguage };
+ _logger.Debug("Language couldn't be parsed from release, fallback to movie original language: {0}", movie.OriginalLanguage.Name);
+ }
+
var localEpisode = new LocalMovie
{
Movie = movie,
@@ -108,8 +117,9 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
SceneSource = SceneSource(movie, rootFolder),
ExistingFile = movie.Path.IsParentPath(path),
Size = _diskProvider.GetFileSize(path),
- Languages = (languages?.SingleOrDefault() ?? Language.Unknown) == Language.Unknown ? LanguageParser.ParseLanguages(path) : languages,
- Quality = quality.Quality == Quality.Unknown ? QualityParser.ParseQuality(path) : quality
+ Languages = (languages?.SingleOrDefault() ?? Language.Unknown) == Language.Unknown ? languageParse : languages,
+ Quality = quality.Quality == Quality.Unknown ? QualityParser.ParseQuality(path) : quality,
+ ReleaseGroup = releaseGroup.IsNullOrWhiteSpace() ? Parser.Parser.ParseReleaseGroup(path) : releaseGroup,
};
return MapItem(_importDecisionMaker.GetDecision(localEpisode, downloadClientItem), rootFolder, downloadId, null);
@@ -118,6 +128,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
private List ProcessFolder(string rootFolder, string baseFolder, string downloadId, int? movieId, bool filterExistingFiles)
{
DownloadClientItem downloadClientItem = null;
+
var directoryInfo = new DirectoryInfo(baseFolder);
var movie = movieId.HasValue ?
@@ -165,50 +176,58 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
private ManualImportItem ProcessFile(string rootFolder, string baseFolder, string file, string downloadId, Movie movie = null)
{
- var trackedDownload = GetTrackedDownload(downloadId);
- var relativeFile = baseFolder.GetRelativePath(file);
-
- if (movie == null)
+ try
{
- movie = _parsingService.GetMovie(relativeFile.Split('\\', '/')[0]);
- }
+ var trackedDownload = GetTrackedDownload(downloadId);
+ var relativeFile = baseFolder.GetRelativePath(file);
- if (movie == null)
- {
- movie = _parsingService.GetMovie(relativeFile);
- }
+ if (movie == null)
+ {
+ movie = _parsingService.GetMovie(relativeFile.Split('\\', '/')[0]);
+ }
- if (trackedDownload != null && movie == null)
- {
- movie = trackedDownload?.RemoteMovie?.Movie;
- }
+ if (movie == null)
+ {
+ movie = _parsingService.GetMovie(relativeFile);
+ }
- if (movie == null)
- {
- var relativeParseInfo = Parser.Parser.ParseMoviePath(relativeFile);
+ if (trackedDownload != null && movie == null)
+ {
+ movie = trackedDownload?.RemoteMovie?.Movie;
+ }
- if (relativeParseInfo != null)
+ if (movie == null)
{
- movie = _movieService.FindByTitle(relativeParseInfo.PrimaryMovieTitle, relativeParseInfo.Year);
+ var relativeParseInfo = Parser.Parser.ParseMoviePath(relativeFile);
+
+ if (relativeParseInfo != null)
+ {
+ movie = _movieService.FindByTitle(relativeParseInfo.PrimaryMovieTitle, relativeParseInfo.Year);
+ }
}
- }
- if (movie == null)
- {
- var localMovie = new LocalMovie();
- localMovie.Path = file;
- localMovie.Quality = QualityParser.ParseQuality(file);
- localMovie.Languages = LanguageParser.ParseLanguages(file);
- localMovie.Size = _diskProvider.GetFileSize(file);
+ if (movie == null)
+ {
+ var localMovie = new LocalMovie();
+ localMovie.Path = file;
+ localMovie.FileMovieInfo = Parser.Parser.ParseMoviePath(file);
+ localMovie.DownloadClientMovieInfo = trackedDownload?.RemoteMovie?.ParsedMovieInfo;
- return MapItem(new ImportDecision(localMovie, new Rejection("Unknown Movie")), rootFolder, downloadId, null);
- }
+ localMovie = _aggregationService.Augment(localMovie, null, false);
- var importDecisions = _importDecisionMaker.GetImportDecisions(new List { file }, movie, trackedDownload?.DownloadItem, null, SceneSource(movie, baseFolder));
+ return MapItem(new ImportDecision(localMovie, new Rejection("Unknown Movie")), rootFolder, downloadId, null);
+ }
- if (importDecisions.Any())
+ var importDecisions = _importDecisionMaker.GetImportDecisions(new List { file }, movie, trackedDownload?.DownloadItem, null, SceneSource(movie, baseFolder));
+
+ if (importDecisions.Any())
+ {
+ return MapItem(importDecisions.First(), rootFolder, downloadId, null);
+ }
+ }
+ catch (Exception ex)
{
- return MapItem(importDecisions.First(), rootFolder, downloadId, null);
+ _logger.Warn(ex, "Failed to process file: {0}", file);
}
return new ManualImportItem
@@ -231,6 +250,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
localEpisode.Path = file;
localEpisode.Quality = new QualityModel(Quality.Unknown);
localEpisode.Languages = new List { Language.Unknown };
+ localEpisode.ReleaseGroup = Parser.Parser.ParseReleaseGroup(file);
localEpisode.Size = _diskProvider.GetFileSize(file);
items.Add(MapItem(new ImportDecision(localEpisode), rootFolder, null, null));
@@ -274,6 +294,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
item.Quality = decision.LocalMovie.Quality;
item.Size = _diskProvider.GetFileSize(decision.LocalMovie.Path);
item.Languages = decision.LocalMovie.Languages;
+ item.ReleaseGroup = decision.LocalMovie.ReleaseGroup;
item.Rejections = decision.Rejections;
return item;
@@ -303,6 +324,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
Path = file.Path,
Quality = file.Quality,
Languages = file.Languages,
+ ReleaseGroup = file.ReleaseGroup,
Movie = movie,
Size = 0
};
@@ -325,6 +347,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport.Manual
localMovie.Movie = movie;
localMovie.Quality = file.Quality;
localMovie.Languages = file.Languages;
+ localMovie.ReleaseGroup = file.ReleaseGroup;
//TODO: Cleanup non-tracked downloads
var importDecision = new ImportDecision(localMovie);
diff --git a/src/Radarr.Api.V3/ManualImport/ManualImportController.cs b/src/Radarr.Api.V3/ManualImport/ManualImportController.cs
index 88d8b5896..769f94cba 100644
--- a/src/Radarr.Api.V3/ManualImport/ManualImportController.cs
+++ b/src/Radarr.Api.V3/ManualImport/ManualImportController.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
+using NzbDrone.Common.Extensions;
using NzbDrone.Core.Languages;
using NzbDrone.Core.MediaFiles.MovieImport.Manual;
using NzbDrone.Core.Qualities;
@@ -30,7 +31,7 @@ namespace Radarr.Api.V3.ManualImport
{
foreach (var item in items)
{
- var processedItem = _manualImportService.ReprocessItem(item.Path, item.DownloadId, item.MovieId, item.Quality, item.Languages);
+ var processedItem = _manualImportService.ReprocessItem(item.Path, item.DownloadId, item.MovieId, item.ReleaseGroup, item.Quality, item.Languages);
item.Movie = processedItem.Movie.ToResource(0);
item.Rejections = processedItem.Rejections;
@@ -43,6 +44,11 @@ namespace Radarr.Api.V3.ManualImport
{
item.Quality = processedItem.Quality;
}
+
+ if (item.ReleaseGroup.IsNotNullOrWhiteSpace())
+ {
+ item.ReleaseGroup = processedItem.ReleaseGroup;
+ }
}
return items;
diff --git a/src/Radarr.Api.V3/ManualImport/ManualImportReprocessResource.cs b/src/Radarr.Api.V3/ManualImport/ManualImportReprocessResource.cs
index f610efbc5..4999ae42d 100644
--- a/src/Radarr.Api.V3/ManualImport/ManualImportReprocessResource.cs
+++ b/src/Radarr.Api.V3/ManualImport/ManualImportReprocessResource.cs
@@ -14,6 +14,7 @@ namespace Radarr.Api.V3.ManualImport
public MovieResource Movie { get; set; }
public QualityModel Quality { get; set; }
public List Languages { get; set; }
+ public string ReleaseGroup { get; set; }
public string DownloadId { get; set; }
public IEnumerable Rejections { get; set; }
diff --git a/src/Radarr.Api.V3/ManualImport/ManualImportResource.cs b/src/Radarr.Api.V3/ManualImport/ManualImportResource.cs
index da6204c04..63c698c77 100644
--- a/src/Radarr.Api.V3/ManualImport/ManualImportResource.cs
+++ b/src/Radarr.Api.V3/ManualImport/ManualImportResource.cs
@@ -20,6 +20,7 @@ namespace Radarr.Api.V3.ManualImport
public MovieResource Movie { get; set; }
public QualityModel Quality { get; set; }
public List Languages { get; set; }
+ public string ReleaseGroup { get; set; }
public int QualityWeight { get; set; }
public string DownloadId { get; set; }
public IEnumerable Rejections { get; set; }
@@ -45,6 +46,7 @@ namespace Radarr.Api.V3.ManualImport
Movie = model.Movie.ToResource(0),
Quality = model.Quality,
Languages = model.Languages,
+ ReleaseGroup = model.ReleaseGroup,
//QualityWeight
DownloadId = model.DownloadId,