1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-09-11 03:52:33 +02:00

New: AddMovieService to validate and populate incomplete adds

This commit is contained in:
Qstick 2020-05-13 22:19:22 -04:00
parent 8b06df1b1a
commit 93d27c70c4
15 changed files with 439 additions and 224 deletions

View File

@ -28,11 +28,13 @@ public class MovieModule : RadarrRestModuleWithSignalR<MovieResource, Movie>,
{
private const string TITLE_SLUG_ROUTE = "/titleslug/(?<slug>[^/]+)";
protected readonly IMovieService _moviesService;
private readonly IMovieService _movieService;
private readonly IAddMovieService _addMovieService;
private readonly IMapCoversToLocal _coverMapper;
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
IMovieService moviesService,
IMovieService movieService,
IAddMovieService addMovieService,
IMapCoversToLocal coverMapper,
RootFolderValidator rootFolderValidator,
MappedNetworkDriveValidator mappedNetworkDriveValidator,
@ -43,7 +45,8 @@ public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
ProfileExistsValidator profileExistsValidator)
: base(signalRBroadcaster)
{
_moviesService = moviesService;
_movieService = movieService;
_addMovieService = addMovieService;
_coverMapper = coverMapper;
@ -80,7 +83,7 @@ public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
private MovieResource GetMovie(int id)
{
var movies = _moviesService.GetMovie(id);
var movies = _movieService.GetMovie(id);
return MapToResource(movies);
}
@ -99,7 +102,7 @@ protected MovieResource MapToResource(Movie movies)
private List<MovieResource> AllMovie()
{
var moviesResources = _moviesService.GetAllMovies().ToResource();
var moviesResources = _movieService.GetAllMovies().ToResource();
MapCoversToLocal(moviesResources.ToArray());
@ -110,14 +113,14 @@ private int AddMovie(MovieResource moviesResource)
{
var model = moviesResource.ToModel();
return _moviesService.AddMovie(model).Id;
return _addMovieService.AddMovie(model).Id;
}
private void UpdateMovie(MovieResource moviesResource)
{
var model = moviesResource.ToModel(_moviesService.GetMovie(moviesResource.Id));
var model = moviesResource.ToModel(_movieService.GetMovie(moviesResource.Id));
_moviesService.UpdateMovie(model);
_movieService.UpdateMovie(model);
BroadcastResourceChange(ModelAction.Updated, moviesResource);
}
@ -139,7 +142,7 @@ private void DeleteMovie(int id)
addExclusion = Convert.ToBoolean(addExclusionQuery.Value);
}
_moviesService.DeleteMovie(id, deleteFiles, addExclusion);
_movieService.DeleteMovie(id, deleteFiles, addExclusion);
}
private void MapCoversToLocal(params MovieResource[] movies)

View File

@ -11,13 +11,13 @@ namespace NzbDrone.Api.NetImport
{
public class ListImportModule : NzbDroneApiModule
{
private readonly IMovieService _movieService;
private readonly IAddMovieService _addMovieService;
private readonly ISearchForNewMovie _movieSearch;
public ListImportModule(IMovieService movieService, ISearchForNewMovie movieSearch)
public ListImportModule(IAddMovieService addMovieService, ISearchForNewMovie movieSearch)
: base("/movie/import")
{
_movieService = movieService;
_addMovieService = addMovieService;
_movieSearch = movieSearch;
Put("/", movie => SaveAll());
}
@ -28,7 +28,7 @@ private object SaveAll()
var movies = resources.Select(movieResource => _movieSearch.MapMovieToTmdbMovie(movieResource.ToModel())).Where(m => m != null).DistinctBy(m => m.TmdbId).ToList();
return ResponseWithCode(_movieService.AddMovies(movies).ToResource(), HttpStatusCode.Accepted);
return ResponseWithCode(_addMovieService.AddMovies(movies).ToResource(), HttpStatusCode.Accepted);
}
}
}

View File

@ -1,80 +0,0 @@
using System.Collections.Generic;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.BulkImport
{
[TestFixture]
public class AddMultiMoviesFixture : CoreTest<MovieService>
{
private List<Movie> _fakeMovies;
[SetUp]
public void Setup()
{
_fakeMovies = Builder<Movie>.CreateListOfSize(3).BuildList();
_fakeMovies.ForEach(m =>
{
m.Path = null;
m.RootFolderPath = @"C:\Test\TV";
});
}
[Test]
public void movies_added_event_should_have_proper_path()
{
Mocker.GetMock<IBuildFileNames>()
.Setup(s => s.GetMovieFolder(It.IsAny<Movie>(), null))
.Returns((Movie m, NamingConfig n) => m.Title);
Mocker.GetMock<IMovieRepository>().Setup(s => s.FindByTmdbId(It.IsAny<List<int>>()))
.Returns(new List<Movie>());
var movies = Subject.AddMovies(_fakeMovies);
foreach (Movie movie in movies)
{
movie.Path.Should().NotBeNullOrEmpty();
}
// Subject.GetAllMovies().Should().HaveCount(3);
}
[Test]
public void movies_added_should_ignore_already_added()
{
Mocker.GetMock<IBuildFileNames>()
.Setup(s => s.GetMovieFolder(It.IsAny<Movie>(), null))
.Returns((Movie m, NamingConfig n) => m.Title);
Mocker.GetMock<IMovieRepository>().Setup(s => s.FindByTmdbId(It.IsAny<List<int>>()))
.Returns(new List<Movie> { _fakeMovies[0] });
var movies = Subject.AddMovies(_fakeMovies);
Mocker.GetMock<IMovieRepository>().Verify(v => v.InsertMany(It.Is<List<Movie>>(l => l.Count == 2)));
}
[Test]
public void movies_added_should_ignore_duplicates()
{
Mocker.GetMock<IBuildFileNames>()
.Setup(s => s.GetMovieFolder(It.IsAny<Movie>(), null))
.Returns((Movie m, NamingConfig n) => m.Title);
Mocker.GetMock<IMovieRepository>().Setup(s => s.FindByTmdbId(It.IsAny<List<int>>()))
.Returns(new List<Movie>());
_fakeMovies[2].TmdbId = _fakeMovies[0].TmdbId;
var movies = Subject.AddMovies(_fakeMovies);
Mocker.GetMock<IMovieRepository>().Verify(v => v.InsertMany(It.Is<List<Movie>>(l => l.Count == 2)));
}
}
}

View File

@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.IO;
using FizzWare.NBuilder;
using FluentAssertions;
using FluentValidation;
using FluentValidation.Results;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Credits;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MovieTests
{
[TestFixture]
public class AddMovieFixture : CoreTest<AddMovieService>
{
private Movie _fakeMovie;
[SetUp]
public void Setup()
{
_fakeMovie = Builder<Movie>
.CreateNew()
.With(s => s.Path = null)
.Build();
}
private void GivenValidMovie(int tmdbId)
{
Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(tmdbId, true))
.Returns(new Tuple<Movie, List<Credit>>(_fakeMovie, new List<Credit>()));
}
private void GivenValidPath()
{
Mocker.GetMock<IBuildFileNames>()
.Setup(s => s.GetMovieFolder(It.IsAny<Movie>(), null))
.Returns<Movie, NamingConfig>((c, n) => c.Title);
Mocker.GetMock<IAddMovieValidator>()
.Setup(s => s.Validate(It.IsAny<Movie>()))
.Returns(new ValidationResult());
}
[Test]
public void should_be_able_to_add_a_movie_without_passing_in_title()
{
var newMovie = new Movie
{
TmdbId = 1,
RootFolderPath = @"C:\Test\Movies"
};
GivenValidMovie(newMovie.TmdbId);
GivenValidPath();
var series = Subject.AddMovie(newMovie);
series.Title.Should().Be(_fakeMovie.Title);
}
[Test]
public void should_have_proper_path()
{
var newMovie = new Movie
{
TmdbId = 1,
RootFolderPath = @"C:\Test\Movies"
};
GivenValidMovie(newMovie.TmdbId);
GivenValidPath();
var series = Subject.AddMovie(newMovie);
series.Path.Should().Be(Path.Combine(newMovie.RootFolderPath, _fakeMovie.Title));
}
[Test]
public void should_throw_if_movie_validation_fails()
{
var newMovie = new Movie
{
TmdbId = 1,
Path = @"C:\Test\Movie\Title1"
};
GivenValidMovie(newMovie.TmdbId);
Mocker.GetMock<IAddMovieValidator>()
.Setup(s => s.Validate(It.IsAny<Movie>()))
.Returns(new ValidationResult(new List<ValidationFailure>
{
new ValidationFailure("Path", "Test validation failure")
}));
Assert.Throws<ValidationException>(() => Subject.AddMovie(newMovie));
}
[Test]
public void should_throw_if_movie_cannot_be_found()
{
var newMovie = new Movie
{
TmdbId = 1,
Path = @"C:\Test\Movie\Title1"
};
Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(newMovie.TmdbId, true))
.Throws(new MovieNotFoundException("Movie Not Found"));
Mocker.GetMock<IAddMovieValidator>()
.Setup(s => s.Validate(It.IsAny<Movie>()))
.Returns(new ValidationResult(new List<ValidationFailure>
{
new ValidationFailure("Path", "Test validation failure")
}));
Assert.Throws<ValidationException>(() => Subject.AddMovie(newMovie));
ExceptionVerification.ExpectedErrors(1);
}
}
}

View File

@ -1,36 +0,0 @@
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.MovieTests.MovieServiceTests
{
[TestFixture]
public class AddMovieFixture : CoreTest<MovieService>
{
private Movie _fakeMovie;
[SetUp]
public void Setup()
{
_fakeMovie = Builder<Movie>.CreateNew().Build();
}
[Test]
public void movie_added_event_should_have_proper_path()
{
_fakeMovie.Path = null;
_fakeMovie.RootFolderPath = @"C:\Test\Movies";
Mocker.GetMock<IBuildFileNames>()
.Setup(s => s.GetMovieFolder(_fakeMovie, null))
.Returns(_fakeMovie.Title);
var series = Subject.AddMovie(_fakeMovie);
series.Path.Should().NotBeNull();
}
}
}

View File

@ -0,0 +1,75 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MovieTests
{
[TestFixture]
public class MovieTitleSlugValidatorFixture : CoreTest<MovieTitleSlugValidator>
{
private List<Movie> _movies;
private TestValidator<Movie> _validator;
[SetUp]
public void Setup()
{
_movies = Builder<Movie>.CreateListOfSize(1)
.Build()
.ToList();
_validator = new TestValidator<Movie>
{
v => v.RuleFor(s => s.TitleSlug).SetValidator(Subject)
};
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetAllMovies())
.Returns(_movies);
}
[Test]
public void should_not_be_valid_if_there_is_an_existing_movie_with_the_same_title_slug()
{
var movie = Builder<Movie>.CreateNew()
.With(s => s.Id = 100)
.With(s => s.TitleSlug = _movies.First().TitleSlug)
.Build();
_validator.Validate(movie).IsValid.Should().BeFalse();
}
[Test]
public void should_be_valid_if_there_is_not_an_existing_movie_with_the_same_title_slug()
{
var movie = Builder<Movie>.CreateNew()
.With(s => s.TitleSlug = "MyTitleSlug")
.Build();
_validator.Validate(movie).IsValid.Should().BeTrue();
}
[Test]
public void should_be_valid_if_there_is_an_existing_movie_with_a_null_title_slug()
{
_movies.First().TitleSlug = null;
var movie = Builder<Movie>.CreateNew()
.With(s => s.TitleSlug = "MyTitleSlug")
.Build();
_validator.Validate(movie).IsValid.Should().BeTrue();
}
[Test]
public void should_be_valid_when_updating_an_existing_movie()
{
_validator.Validate(_movies.First().JsonClone()).IsValid.Should().BeTrue();
}
}
}

View File

@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using Moq;
@ -279,7 +279,7 @@ public void should_add_new_movies_from_single_list_to_library()
Subject.Execute(_command);
Mocker.GetMock<IMovieService>()
Mocker.GetMock<IAddMovieService>()
.Verify(v => v.AddMovies(It.Is<List<Movie>>(s => s.Count == 5)), Times.Once());
}
@ -293,7 +293,7 @@ public void should_add_new_movies_from_multiple_list_to_library()
Subject.Execute(_command);
Mocker.GetMock<IMovieService>()
Mocker.GetMock<IAddMovieService>()
.Verify(v => v.AddMovies(It.Is<List<Movie>>(s => s.Count == 8)), Times.Once());
}
@ -307,7 +307,7 @@ public void should_add_new_movies_from_enabled_lists_to_library()
Subject.Execute(_command);
Mocker.GetMock<IMovieService>()
Mocker.GetMock<IAddMovieService>()
.Verify(v => v.AddMovies(It.Is<List<Movie>>(s => s.Count == 5)), Times.Once());
}
@ -323,7 +323,7 @@ public void should_not_add_duplicate_movies_from_seperate_lists()
Subject.Execute(_command);
Mocker.GetMock<IMovieService>()
Mocker.GetMock<IAddMovieService>()
.Verify(v => v.AddMovies(It.Is<List<Movie>>(s => s.Count == 7)), Times.Once());
}
@ -341,7 +341,7 @@ public void should_not_add_movie_from_on_exclusion_list()
Subject.Execute(_command);
Mocker.GetMock<IMovieService>()
Mocker.GetMock<IAddMovieService>()
.Verify(v => v.AddMovies(It.Is<List<Movie>>(s => s.Count == 7 && !s.Any(m => m.TmdbId == _moviesList2[0].TmdbId))), Times.Once());
}
@ -359,7 +359,7 @@ public void should_not_add_movie_that_exists_in_library()
Subject.Execute(_command);
Mocker.GetMock<IMovieService>()
Mocker.GetMock<IAddMovieService>()
.Verify(v => v.AddMovies(It.Is<List<Movie>>(s => s.Count == 7 && !s.Any(m => m.TmdbId == _moviesList2[0].TmdbId))), Times.Once());
}

View File

@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.IO;
using FluentValidation;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common.EnsureThat;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Movies
{
public interface IAddMovieService
{
Movie AddMovie(Movie newMovie);
List<Movie> AddMovies(List<Movie> newMovies);
}
public class AddMovieService : IAddMovieService
{
private readonly IMovieService _movieService;
private readonly IProvideMovieInfo _movieInfo;
private readonly IBuildFileNames _fileNameBuilder;
private readonly IAddMovieValidator _addMovieValidator;
private readonly Logger _logger;
public AddMovieService(IMovieService movieService,
IProvideMovieInfo movieInfo,
IBuildFileNames fileNameBuilder,
IAddMovieValidator addMovieValidator,
Logger logger)
{
_movieService = movieService;
_movieInfo = movieInfo;
_fileNameBuilder = fileNameBuilder;
_addMovieValidator = addMovieValidator;
_logger = logger;
}
public Movie AddMovie(Movie newMovie)
{
Ensure.That(newMovie, () => newMovie).IsNotNull();
newMovie = AddSkyhookData(newMovie);
newMovie = SetPropertiesAndValidate(newMovie);
_logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path);
_movieService.AddMovie(newMovie);
return newMovie;
}
public List<Movie> AddMovies(List<Movie> newMovies)
{
var added = DateTime.UtcNow;
var moviesToAdd = new List<Movie>();
foreach (var m in newMovies)
{
// TODO: Verify if adding skyhook data will be slow
var movie = AddSkyhookData(m);
movie = SetPropertiesAndValidate(movie);
movie.Added = added;
moviesToAdd.Add(movie);
}
return _movieService.AddMovies(moviesToAdd);
}
private Movie AddSkyhookData(Movie newMovie)
{
Movie movie;
try
{
movie = _movieInfo.GetMovieInfo(newMovie.TmdbId, true).Item1;
}
catch (MovieNotFoundException)
{
_logger.Error("TmdbId {1} was not found, it may have been removed from TMDb.", newMovie.TmdbId);
throw new ValidationException(new List<ValidationFailure>
{
new ValidationFailure("TmdbId", "A movie with this ID was not found", newMovie.TmdbId)
});
}
movie.ApplyChanges(newMovie);
return movie;
}
private Movie SetPropertiesAndValidate(Movie newMovie)
{
if (string.IsNullOrWhiteSpace(newMovie.Path))
{
var folderName = _fileNameBuilder.GetMovieFolder(newMovie);
newMovie.Path = Path.Combine(newMovie.RootFolderPath, folderName);
}
newMovie.CleanTitle = newMovie.Title.CleanSeriesTitle();
newMovie.SortTitle = MovieTitleNormalizer.Normalize(newMovie.Title, newMovie.TmdbId);
newMovie.Added = DateTime.UtcNow;
var validationResult = _addMovieValidator.Validate(newMovie);
if (!validationResult.IsValid)
{
throw new ValidationException(validationResult.Errors);
}
return newMovie;
}
}
}

View File

@ -0,0 +1,28 @@
using FluentValidation;
using FluentValidation.Results;
using NzbDrone.Core.Validation.Paths;
namespace NzbDrone.Core.Movies
{
public interface IAddMovieValidator
{
ValidationResult Validate(Movie instance);
}
public class AddMovieValidator : AbstractValidator<Movie>, IAddMovieValidator
{
public AddMovieValidator(RootFolderValidator rootFolderValidator,
MoviePathValidator moviePathValidator,
MovieAncestorValidator movieAncestorValidator,
MovieTitleSlugValidator movieTitleSlugValidator)
{
RuleFor(c => c.Path).Cascade(CascadeMode.StopOnFirstFailure)
.IsValidPath()
.SetValidator(rootFolderValidator)
.SetValidator(moviePathValidator)
.SetValidator(movieAncestorValidator);
RuleFor(c => c.TitleSlug).SetValidator(movieTitleSlugValidator);
}
}
}

View File

@ -94,20 +94,6 @@ public PagingSpec<Movie> Paged(PagingSpec<Movie> pagingSpec)
public Movie AddMovie(Movie newMovie)
{
Ensure.That(newMovie, () => newMovie).IsNotNull();
if (string.IsNullOrWhiteSpace(newMovie.Path))
{
var folderName = _fileNameBuilder.GetMovieFolder(newMovie);
newMovie.Path = Path.Combine(newMovie.RootFolderPath, folderName);
}
_logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path);
newMovie.CleanTitle = newMovie.Title.CleanSeriesTitle();
newMovie.SortTitle = MovieTitleNormalizer.Normalize(newMovie.Title, newMovie.TmdbId);
newMovie.Added = DateTime.UtcNow;
_movieRepository.Insert(newMovie);
_eventAggregator.PublishEvent(new MovieAddedEvent(GetMovie(newMovie.Id)));
@ -116,33 +102,7 @@ public Movie AddMovie(Movie newMovie)
public List<Movie> AddMovies(List<Movie> newMovies)
{
newMovies.ForEach(m => Ensure.That(m, () => m).IsNotNull());
newMovies.ForEach(m =>
{
if (string.IsNullOrWhiteSpace(m.Path))
{
var folderName = _fileNameBuilder.GetMovieFolder(m);
m.Path = Path.Combine(m.RootFolderPath, folderName);
}
m.CleanTitle = m.Title.CleanSeriesTitle();
m.SortTitle = MovieTitleNormalizer.Normalize(m.Title, m.TmdbId);
m.Added = DateTime.UtcNow;
});
var potentialMovieCount = newMovies.Count;
newMovies = newMovies.DistinctBy(movie => movie.TmdbId).ToList(); // Ensure we don't add the same movie twice
var existingMovies = FindByTmdbId(newMovies.Select(x => x.TmdbId).ToList());
newMovies = newMovies.ExceptBy(n => n.TmdbId, existingMovies, e => e.TmdbId, EqualityComparer<int>.Default).ToList(); // Ensure we don't add a movie that already exists
_movieRepository.InsertMany(newMovies);
_logger.Debug("Adding {0} movies, {1} duplicates detected and skipped", newMovies.Count, potentialMovieCount - newMovies.Count);
_eventAggregator.PublishEvent(new MoviesImportedEvent(newMovies.Select(s => s.Id).ToList()));
return newMovies;
@ -161,13 +121,13 @@ public Movie FindByTitle(string title, int year)
private Movie FindByTitle(string cleanTitle, int? year)
{
cleanTitle = cleanTitle.ToLowerInvariant();
string cleanTitleWithRomanNumbers = cleanTitle;
string cleanTitleWithArabicNumbers = cleanTitle;
var cleanTitleWithRomanNumbers = cleanTitle;
var cleanTitleWithArabicNumbers = cleanTitle;
foreach (ArabicRomanNumeral arabicRomanNumeral in RomanNumeralParser.GetArabicRomanNumeralsMapping())
foreach (var arabicRomanNumeral in RomanNumeralParser.GetArabicRomanNumeralsMapping())
{
string arabicNumber = arabicRomanNumeral.ArabicNumeralAsString;
string romanNumber = arabicRomanNumeral.RomanNumeral;
var arabicNumber = arabicRomanNumeral.ArabicNumeralAsString;
var romanNumber = arabicRomanNumeral.RomanNumeral;
cleanTitleWithRomanNumbers = cleanTitleWithRomanNumbers.Replace(arabicNumber, romanNumber);
cleanTitleWithArabicNumbers = cleanTitleWithArabicNumbers.Replace(romanNumber, arabicNumber);
}

View File

@ -0,0 +1,44 @@
using System.Linq;
using FluentValidation.Validators;
using NzbDrone.Common.Extensions;
namespace NzbDrone.Core.Movies
{
public class MovieTitleSlugValidator : PropertyValidator
{
private readonly IMovieService _movieService;
public MovieTitleSlugValidator(IMovieService movieService)
: base("Title slug '{slug}' is in use by movie '{movieTitle}'")
{
_movieService = movieService;
}
protected override bool IsValid(PropertyValidatorContext context)
{
if (context.PropertyValue == null)
{
return true;
}
dynamic instance = context.ParentContext.InstanceToValidate;
var instanceId = (int)instance.Id;
var slug = context.PropertyValue.ToString();
var conflictingMovie = _movieService.GetAllMovies()
.FirstOrDefault(s => s.TitleSlug.IsNotNullOrWhiteSpace() &&
s.TitleSlug.Equals(context.PropertyValue.ToString()) &&
s.Id != instanceId);
if (conflictingMovie == null)
{
return true;
}
context.MessageFormatter.AppendArgument("slug", slug);
context.MessageFormatter.AppendArgument("movieTitle", conflictingMovie.Title);
return false;
}
}
}

View File

@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common.Extensions;
@ -21,12 +21,14 @@ public class NetImportSearchService : IFetchNetImport, IExecute<NetImportSyncCom
private readonly Logger _logger;
private readonly INetImportFactory _netImportFactory;
private readonly IMovieService _movieService;
private readonly IAddMovieService _addMovieService;
private readonly ISearchForNewMovie _movieSearch;
private readonly IConfigService _configService;
private readonly IImportExclusionsService _exclusionService;
public NetImportSearchService(INetImportFactory netImportFactory,
IMovieService movieService,
IAddMovieService addMovieService,
ISearchForNewMovie movieSearch,
IConfigService configService,
IImportExclusionsService exclusionService,
@ -34,6 +36,7 @@ public NetImportSearchService(INetImportFactory netImportFactory,
{
_netImportFactory = netImportFactory;
_movieService = movieService;
_addMovieService = addMovieService;
_movieSearch = movieSearch;
_exclusionService = exclusionService;
_logger = logger;
@ -151,7 +154,7 @@ public void Execute(NetImportSyncCommand message)
_logger.Info($"Adding {moviesToAdd.Count()} movies from your auto enabled lists to library");
}
_movieService.AddMovies(moviesToAdd);
_addMovieService.AddMovies(moviesToAdd);
}
private void CleanLibrary(List<Movie> movies)

View File

@ -8,21 +8,21 @@ namespace Radarr.Api.V3.Movies
{
public class MovieImportModule : RadarrRestModule<MovieResource>
{
private readonly IMovieService _movieService;
private readonly IAddMovieService _addMovieService;
public MovieImportModule(IMovieService movieService)
public MovieImportModule(IAddMovieService addMovieService)
: base("/movie/import")
{
_movieService = movieService;
_addMovieService = addMovieService;
Post("/", x => Import());
}
private object Import()
{
var resource = Request.Body.FromJson<List<MovieResource>>();
var newSeries = resource.ToModel();
var newMovies = resource.ToModel();
return _movieService.AddMovies(newSeries).ToResource();
return _addMovieService.AddMovies(newMovies).ToResource();
}
}
}

View File

@ -29,13 +29,15 @@ public class MovieModule : RadarrRestModuleWithSignalR<MovieResource, Movie>,
IHandle<MovieRenamedEvent>,
IHandle<MediaCoversUpdatedEvent>
{
protected readonly IMovieService _moviesService;
private readonly IMovieService _moviesService;
private readonly IAddMovieService _addMovieService;
private readonly IMapCoversToLocal _coverMapper;
private readonly IManageCommandQueue _commandQueueManager;
private readonly IUpgradableSpecification _qualityUpgradableSpecification;
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
IMovieService moviesService,
IAddMovieService addMovieService,
IMapCoversToLocal coverMapper,
IManageCommandQueue commandQueueManager,
IUpgradableSpecification qualityUpgradableSpecification,
@ -50,6 +52,7 @@ public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
: base(signalRBroadcaster)
{
_moviesService = moviesService;
_addMovieService = addMovieService;
_qualityUpgradableSpecification = qualityUpgradableSpecification;
_coverMapper = coverMapper;
_commandQueueManager = commandQueueManager;
@ -126,7 +129,7 @@ protected MovieResource MapToResource(Movie movies)
private int AddMovie(MovieResource moviesResource)
{
var movie = _moviesService.AddMovie(moviesResource.ToModel());
var movie = _addMovieService.AddMovie(moviesResource.ToModel());
return movie.Id;
}

View File

@ -1,34 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Nancy;
using Nancy.Extensions;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Movies;
using Radarr.Api.V3.Movies;
using Radarr.Http.Extensions;
namespace Radarr.Api.V3.NetImport
{
public class ListImportModule : RadarrV3Module
{
private readonly IMovieService _movieService;
private readonly ISearchForNewMovie _movieSearch;
public ListImportModule(IMovieService movieService, ISearchForNewMovie movieSearch)
: base("/movie/import")
{
_movieService = movieService;
_movieSearch = movieSearch;
Put("/", movie => SaveAll());
}
private object SaveAll()
{
var resources = Request.Body.FromJson<List<MovieResource>>();
var movies = resources.Select(movieResource => _movieSearch.MapMovieToTmdbMovie(movieResource.ToModel())).Where(m => m != null).DistinctBy(m => m.TmdbId).ToList();
return ResponseWithCode(_movieService.AddMovies(movies).ToResource(), HttpStatusCode.Accepted);
}
}
}