Fixed: When refreshing info about a movie, the alt titles should now correctly be deleted / updated, even from TMDB. (#3603)

* Fixed: When refreshing info about a movie, the alt titles should now correctly be deleted / updated, even from TMDB.
Fixes #3542

* Fixed: Small things fixup.
pull/2/head
Leonardo Galli 6 years ago committed by Qstick
parent bd374825f1
commit be3152e630

@ -0,0 +1,32 @@
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Movies.AlternativeTitles;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
{
[TestFixture]
public class AlternativeTitleFixture : CoreTest
{
private AlternativeTitle CreateFakeTitle(SourceType source, int votes)
{
return Builder<AlternativeTitle>.CreateNew().With(t => t.SourceType = source).With(t => t.Votes = votes)
.Build();
}
[TestCase(SourceType.TMDB, -1, true)]
[TestCase(SourceType.TMDB, 1000, true)]
[TestCase(SourceType.Mappings, 0, false)]
[TestCase(SourceType.Mappings, 4, true)]
[TestCase(SourceType.Mappings, -1, false)]
[TestCase(SourceType.Indexer, 0, true)]
[TestCase(SourceType.User, 0, true)]
public void should_be_trusted(SourceType source, int votes, bool trusted)
{
var fakeTitle = CreateFakeTitle(source, votes);
fakeTitle.IsTrusted().Should().Be(trusted);
}
}
}

@ -0,0 +1,104 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.AlternativeTitles;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.MovieTests.AlternativeTitleServiceTests
{
[TestFixture]
public class AlternativeTitleServiceFixture : CoreTest<AlternativeTitleService>
{
private AlternativeTitle _title1;
private AlternativeTitle _title2;
private AlternativeTitle _title3;
private Movie _movie;
[SetUp]
public void Setup()
{
var titles = Builder<AlternativeTitle>.CreateListOfSize(3).All().With(t => t.MovieId = 0).Build();
_title1 = titles[0];
_title2 = titles[1];
_title3 = titles[2];
_movie = Builder<Movie>.CreateNew().With(m => m.CleanTitle = "myothertitle").With(m => m.Id = 1).Build();
}
private void GivenExistingTitles(params AlternativeTitle[] titles)
{
Mocker.GetMock<IAlternativeTitleRepository>().Setup(r => r.FindByMovieId(_movie.Id))
.Returns(titles.ToList());
}
[Test]
public void should_update_insert_remove_titles()
{
var titles = new List<AlternativeTitle> {_title2, _title3};
var updates = new List<AlternativeTitle> {_title2};
var deletes = new List<AlternativeTitle> {_title1};
var inserts = new List<AlternativeTitle> {_title3};
GivenExistingTitles(_title1, _title2);
Subject.UpdateTitles(titles, _movie);
Mocker.GetMock<IAlternativeTitleRepository>().Verify(r => r.InsertMany(inserts), Times.Once());
Mocker.GetMock<IAlternativeTitleRepository>().Verify(r => r.UpdateMany(updates), Times.Once());
Mocker.GetMock<IAlternativeTitleRepository>().Verify(r => r.DeleteMany(deletes), Times.Once());
}
[Test]
public void should_not_insert_duplicates()
{
GivenExistingTitles();
var titles = new List<AlternativeTitle> {_title1, _title1};
var inserts = new List<AlternativeTitle>{ _title1 };
Subject.UpdateTitles(titles, _movie);
Mocker.GetMock<IAlternativeTitleRepository>().Verify(r => r.InsertMany(inserts), Times.Once());
}
[Test]
public void should_not_insert_main_title()
{
GivenExistingTitles();
var titles = new List<AlternativeTitle>{_title1};
var movie = Builder<Movie>.CreateNew().With(m => m.CleanTitle = _title1.CleanTitle).Build();
Subject.UpdateTitles(titles, movie);
Mocker.GetMock<IAlternativeTitleRepository>().Verify(r => r.InsertMany(new List<AlternativeTitle>()), Times.Once());
}
[Test]
public void should_update_movie_id()
{
GivenExistingTitles();
var titles = new List<AlternativeTitle> {_title1, _title2};
Subject.UpdateTitles(titles, _movie);
_title1.MovieId.Should().Be(_movie.Id);
_title2.MovieId.Should().Be(_movie.Id);
}
[Test]
public void should_update_with_correct_id()
{
var existingTitle = Builder<AlternativeTitle>.CreateNew().With(t => t.Id = 2).Build();
GivenExistingTitles(existingTitle);
var updateTitle = existingTitle.JsonClone();
updateTitle.Id = 0;
Subject.UpdateTitles(new List<AlternativeTitle> {updateTitle}, _movie);
Mocker.GetMock<IAlternativeTitleRepository>().Verify(r => r.UpdateMany(It.Is<IList<AlternativeTitle>>(list => list.First().Id == existingTitle.Id)), Times.Once());
}
}
}

@ -33,15 +33,15 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
Language = language ?? Language.English; Language = language ?? Language.English;
} }
public bool IsTrusted(int minVotes = 3) public bool IsTrusted(int minVotes = 4)
{ {
switch (SourceType) switch (SourceType)
{ {
case SourceType.TMDB: case SourceType.Mappings:
return Votes >= minVotes; return Votes >= minVotes;
default: default:
return true; return true;
} }
} }
public override bool Equals(object obj) public override bool Equals(object obj)

@ -1,5 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.Linq; using System.Linq;
using Marr.Data;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;

@ -3,6 +3,7 @@ using NzbDrone.Core.Configuration;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Movies.Events; using NzbDrone.Core.Movies.Events;
namespace NzbDrone.Core.Movies.AlternativeTitles namespace NzbDrone.Core.Movies.AlternativeTitles
@ -14,7 +15,7 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
List<AlternativeTitle> AddAltTitles(List<AlternativeTitle> titles, Movie movie); List<AlternativeTitle> AddAltTitles(List<AlternativeTitle> titles, Movie movie);
AlternativeTitle GetById(int id); AlternativeTitle GetById(int id);
List<AlternativeTitle> GetAllTitles(); List<AlternativeTitle> GetAllTitles();
void DeleteNotEnoughVotes(List<AlternativeTitle> mappingsTitles); List<AlternativeTitle> UpdateTitles(List<AlternativeTitle> titles, Movie movie);
} }
public class AlternativeTitleService : IAlternativeTitleService, IHandleAsync<MovieDeletedEvent> public class AlternativeTitleService : IAlternativeTitleService, IHandleAsync<MovieDeletedEvent>
@ -69,11 +70,28 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
_titleRepo.Delete(title); _titleRepo.Delete(title);
} }
public void DeleteNotEnoughVotes(List<AlternativeTitle> mappingsTitles) public List<AlternativeTitle> UpdateTitles(List<AlternativeTitle> titles, Movie movie)
{ {
var toRemove = mappingsTitles.Where(t => t.SourceType == SourceType.Mappings && t.Votes < 4); int movieId = movie.Id;
var realT = _titleRepo.FindBySourceIds(toRemove.Select(t => t.SourceId).ToList()); // First update the movie ids so we can correlate them later.
_titleRepo.DeleteMany(realT); titles.ForEach(t => t.MovieId = movieId);
// Then make sure none of them are the same as the main title.
titles = titles.Where(t => t.CleanTitle != movie.CleanTitle).ToList();
// Then make sure they are all distinct titles
titles = titles.DistinctBy(t => t.CleanTitle).ToList();
// Now find titles to delete, update and insert.
var existingTitles = _titleRepo.FindByMovieId(movieId);
var insert = titles.Where(t => !existingTitles.Contains(t));
var update = existingTitles.Where(t => titles.Contains(t));
var delete = existingTitles.Where(t => !titles.Contains(t));
_titleRepo.DeleteMany(delete.ToList());
_titleRepo.UpdateMany(update.ToList());
_titleRepo.InsertMany(insert.ToList());
return titles;
} }
public void HandleAsync(MovieDeletedEvent message) public void HandleAsync(MovieDeletedEvent message)

@ -104,26 +104,16 @@ namespace NzbDrone.Core.Movies
_logger.Warn(e, "Couldn't update movie path for " + movie.Path); _logger.Warn(e, "Couldn't update movie path for " + movie.Path);
} }
movieInfo.AlternativeTitles = movieInfo.AlternativeTitles.Where(t => t.CleanTitle != movie.CleanTitle)
.DistinctBy(t => t.CleanTitle)
.ExceptBy(t => t.CleanTitle, movie.AlternativeTitles, t => t.CleanTitle, EqualityComparer<string>.Default).ToList();
try try
{ {
movie.AlternativeTitles.AddRange(_titleService.AddAltTitles(movieInfo.AlternativeTitles, movie));
var mappings = _apiClient.AlternativeTitlesAndYearForMovie(movieInfo.TmdbId); var mappings = _apiClient.AlternativeTitlesAndYearForMovie(movieInfo.TmdbId);
var mappingsTitles = mappings.Item1; var mappingsTitles = mappings.Item1;
_titleService.DeleteNotEnoughVotes(mappingsTitles); mappingsTitles = mappingsTitles.Where(t => t.IsTrusted()).ToList();
mappingsTitles = mappingsTitles.ExceptBy(t => t.CleanTitle, movie.AlternativeTitles,
t => t.CleanTitle, EqualityComparer<string>.Default).ToList();
movieInfo.AlternativeTitles.AddRange(mappingsTitles);
mappingsTitles = mappingsTitles.Where(t => t.Votes > 3).ToList();
movie.AlternativeTitles = _titleService.UpdateTitles(movieInfo.AlternativeTitles, movie);
movie.AlternativeTitles.AddRange(_titleService.AddAltTitles(mappingsTitles, movie));
if (mappings.Item2 != null) if (mappings.Item2 != null)
{ {

Loading…
Cancel
Save