diff --git a/NzbDrone.Core.Test/EpisodeProviderTest.cs b/NzbDrone.Core.Test/EpisodeProviderTest.cs index a054ff14a..ebe9295b9 100644 --- a/NzbDrone.Core.Test/EpisodeProviderTest.cs +++ b/NzbDrone.Core.Test/EpisodeProviderTest.cs @@ -1231,5 +1231,83 @@ namespace NzbDrone.Core.Test mocker.VerifyAllMocks(); } + + [Test] + public void EpisodesWithFiles_success() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(); + mocker.SetConstant(db); + + var series = Builder.CreateNew() + .With(s => s.SeriesId = 10) + .Build(); + + var episodeFile = Builder.CreateNew() + .With(c => c.EpisodeFileId = 1) + .Build(); + + var episodes = Builder.CreateListOfSize(2) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 1) + .Have(c => c.AirDate = DateTime.Today.AddDays(-4)) + .Have(c => c.Ignored = true) + .Have(c => c.EpisodeFile = episodeFile) + .Have(c => c.EpisodeFileId = episodeFile.EpisodeFileId) + .Build().ToList(); + + db.Insert(series); + db.Insert(episodeFile); + db.InsertMany(episodes); + + //Act + var withFiles = mocker.Resolve().EpisodesWithFiles(); + + //Assert + withFiles.Should().HaveCount(2); + withFiles.Where(e => e.EpisodeFileId == 0).Should().HaveCount(0); + withFiles.Where(e => e.EpisodeFile == null).Should().HaveCount(0); + + foreach (var withFile in withFiles) + { + withFile.EpisodeFile.Should().NotBeNull(); + withFile.SeriesTitle.Should().NotBeNullOrEmpty(); + } + + mocker.VerifyAllMocks(); + } + + [Test] + public void EpisodesWithFiles_no_files() + { + var db = MockLib.GetEmptyDatabase(); + var mocker = new AutoMoqer(); + mocker.SetConstant(db); + + var series = Builder.CreateNew() + .With(s => s.SeriesId = 10) + .Build(); + + var episodes = Builder.CreateListOfSize(2) + .WhereAll() + .Have(c => c.SeriesId = 10) + .Have(c => c.SeasonNumber = 1) + .Have(c => c.AirDate = DateTime.Today.AddDays(-4)) + .Have(c => c.Ignored = true) + .Have(c => c.EpisodeFileId = 0) + .Build().ToList(); + + db.Insert(series); + db.InsertMany(episodes); + + //Act + var withFiles = mocker.Resolve().EpisodesWithFiles(); + + //Assert + withFiles.Should().HaveCount(0); + + mocker.VerifyAllMocks(); + } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/Framework/MockLib.cs b/NzbDrone.Core.Test/Framework/MockLib.cs index 9cf224e7f..c220858f1 100644 --- a/NzbDrone.Core.Test/Framework/MockLib.cs +++ b/NzbDrone.Core.Test/Framework/MockLib.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using FizzWare.NBuilder; using Moq; using NzbDrone.Core.Datastore; diff --git a/NzbDrone.Core.Test/MediaFileProviderTests.cs b/NzbDrone.Core.Test/MediaFileProviderTests.cs index 71170266e..fbe54be1d 100644 --- a/NzbDrone.Core.Test/MediaFileProviderTests.cs +++ b/NzbDrone.Core.Test/MediaFileProviderTests.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Linq.Expressions; using AutoMoq; using FizzWare.NBuilder; diff --git a/NzbDrone.Core.Test/MisnamedProviderTest.cs b/NzbDrone.Core.Test/MisnamedProviderTest.cs new file mode 100644 index 000000000..9028e00ff --- /dev/null +++ b/NzbDrone.Core.Test/MisnamedProviderTest.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Generic; +using System.Text; +using AutoMoq; +using FizzWare.NBuilder; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Core.Model.Notification; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.Jobs; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test +{ + [TestFixture] + public class MisnamedProviderTest + { + [Test] + public void no_misnamed_files() + { + //Setup + var episodeFiles = Builder.CreateListOfSize(2) + .WhereTheFirst(1) + .Has(f => f.EpisodeFileId = 1) + .Has(f => f.Path = @"C:\Test\Title1.avi") + .AndTheNext(1) + .Has(f => f.EpisodeFileId = 2) + .Has(f => f.Path = @"C:\Test\Title2.avi") + .Build(); + + var episodes = Builder.CreateListOfSize(2) + .WhereTheFirst(1) + .Has(e => e.EpisodeFileId = 1) + .Has(e => e.EpisodeFile = episodeFiles[0]) + .Has(e => e.SeriesTitle = "SeriesTitle1") + .AndTheNext(1) + .Has(e => e.EpisodeFileId = 2) + .Has(e => e.EpisodeFile = episodeFiles[1]) + .Has(e => e.SeriesTitle = "SeriesTitle2") + .Build(); + + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(c => c.EpisodesWithFiles()).Returns(episodes); + + mocker.GetMock() + .Setup(c => c.GetNewFilename(new List {episodes[0]}, "SeriesTitle1", It.IsAny())) + .Returns("Title1"); + + mocker.GetMock() + .Setup(c => c.GetNewFilename(new List {episodes[1]}, "SeriesTitle2", It.IsAny())) + .Returns("Title2"); + + //Act + var totalItems = 0; + var misnamedEpisodes = mocker.Resolve().MisnamedFiles(1, 10, out totalItems); + + //Assert + misnamedEpisodes.Should().HaveCount(0); + } + + [Test] + public void all_misnamed_files() + { + //Setup + var episodeFiles = Builder.CreateListOfSize(2) + .WhereTheFirst(1) + .Has(f => f.EpisodeFileId = 1) + .Has(f => f.Path = @"C:\Test\Title1.avi") + .AndTheNext(1) + .Has(f => f.EpisodeFileId = 2) + .Has(f => f.Path = @"C:\Test\Title2.avi") + .Build(); + + var episodes = Builder.CreateListOfSize(2) + .WhereTheFirst(1) + .Has(e => e.EpisodeFileId = 1) + .Has(e => e.EpisodeFile = episodeFiles[0]) + .Has(e => e.SeriesTitle = "SeriesTitle1") + .AndTheNext(1) + .Has(e => e.EpisodeFileId = 2) + .Has(e => e.EpisodeFile = episodeFiles[1]) + .Has(e => e.SeriesTitle = "SeriesTitle2") + .Build(); + + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(c => c.EpisodesWithFiles()).Returns(episodes); + + mocker.GetMock() + .Setup(c => c.GetNewFilename(new List { episodes[0] }, "SeriesTitle1", It.IsAny())) + .Returns("New Title 1"); + + mocker.GetMock() + .Setup(c => c.GetNewFilename(new List { episodes[1] }, "SeriesTitle2", It.IsAny())) + .Returns("New Title 2"); + + //Act + var totalItems = 0; + var misnamedEpisodes = mocker.Resolve().MisnamedFiles(1, 10, out totalItems); + + //Assert + misnamedEpisodes.Should().HaveCount(2); + } + + [Test] + public void one_misnamed_file() + { + //Setup + var episodeFiles = Builder.CreateListOfSize(2) + .WhereTheFirst(1) + .Has(f => f.EpisodeFileId = 1) + .Has(f => f.Path = @"C:\Test\Title1.avi") + .AndTheNext(1) + .Has(f => f.EpisodeFileId = 2) + .Has(f => f.Path = @"C:\Test\Title2.avi") + .Build(); + + var episodes = Builder.CreateListOfSize(2) + .WhereTheFirst(1) + .Has(e => e.EpisodeFileId = 1) + .Has(e => e.EpisodeFile = episodeFiles[0]) + .Has(e => e.SeriesTitle = "SeriesTitle1") + .AndTheNext(1) + .Has(e => e.EpisodeFileId = 2) + .Has(e => e.EpisodeFile = episodeFiles[1]) + .Has(e => e.SeriesTitle = "SeriesTitle2") + .Build(); + + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(c => c.EpisodesWithFiles()).Returns(episodes); + + mocker.GetMock() + .Setup(c => c.GetNewFilename(new List { episodes[0] }, "SeriesTitle1", It.IsAny())) + .Returns("New Title 1"); + + mocker.GetMock() + .Setup(c => c.GetNewFilename(new List { episodes[1] }, "SeriesTitle2", It.IsAny())) + .Returns("Title2"); + + //Act + var totalItems = 0; + var misnamedEpisodes = mocker.Resolve().MisnamedFiles(1, 10, out totalItems); + + //Assert + misnamedEpisodes.Should().HaveCount(1); + misnamedEpisodes[0].CurrentName.Should().Be("Title1"); + misnamedEpisodes[0].ProperName.Should().Be("New Title 1"); + } + + [Test] + public void misnamed_multi_episode_file() + { + //Setup + var episodeFiles = Builder.CreateListOfSize(2) + .WhereTheFirst(1) + .Has(f => f.EpisodeFileId = 1) + .Has(f => f.Path = @"C:\Test\Title1.avi") + .AndTheNext(1) + .Has(f => f.EpisodeFileId = 2) + .Has(f => f.Path = @"C:\Test\Title2.avi") + .Build(); + + var episodes = Builder.CreateListOfSize(3) + .WhereTheFirst(2) + .Has(e => e.EpisodeFileId = 1) + .Has(e => e.EpisodeFile = episodeFiles[0]) + .Has(e => e.SeriesTitle = "SeriesTitle1") + .AndTheNext(1) + .Has(e => e.EpisodeFileId = 2) + .Has(e => e.EpisodeFile = episodeFiles[1]) + .Has(e => e.SeriesTitle = "SeriesTitle2") + .Build(); + + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(c => c.EpisodesWithFiles()).Returns(episodes); + + mocker.GetMock() + .Setup(c => c.GetNewFilename(new List { episodes[0], episodes[1] }, "SeriesTitle1", It.IsAny())) + .Returns("New Title 1"); + + mocker.GetMock() + .Setup(c => c.GetNewFilename(new List { episodes[2] }, "SeriesTitle2", It.IsAny())) + .Returns("Title2"); + + //Act + var totalItems = 0; + var misnamedEpisodes = mocker.Resolve().MisnamedFiles(1, 10, out totalItems); + + //Assert + misnamedEpisodes.Should().HaveCount(1); + misnamedEpisodes[0].CurrentName.Should().Be("Title1"); + misnamedEpisodes[0].ProperName.Should().Be("New Title 1"); + } + + [Test] + public void no_misnamed_multi_episode_file() + { + //Setup + var episodeFiles = Builder.CreateListOfSize(2) + .WhereTheFirst(1) + .Has(f => f.EpisodeFileId = 1) + .Has(f => f.Path = @"C:\Test\Title1.avi") + .AndTheNext(1) + .Has(f => f.EpisodeFileId = 2) + .Has(f => f.Path = @"C:\Test\Title2.avi") + .Build(); + + var episodes = Builder.CreateListOfSize(3) + .WhereTheFirst(2) + .Has(e => e.EpisodeFileId = 1) + .Has(e => e.EpisodeFile = episodeFiles[0]) + .Has(e => e.SeriesTitle = "SeriesTitle1") + .AndTheNext(1) + .Has(e => e.EpisodeFileId = 2) + .Has(e => e.EpisodeFile = episodeFiles[1]) + .Has(e => e.SeriesTitle = "SeriesTitle2") + .Build(); + + var mocker = new AutoMoqer(MockBehavior.Strict); + + mocker.GetMock() + .Setup(c => c.EpisodesWithFiles()).Returns(episodes); + + mocker.GetMock() + .Setup(c => c.GetNewFilename(new List { episodes[0], episodes[1] }, "SeriesTitle1", It.IsAny())) + .Returns("Title1"); + + mocker.GetMock() + .Setup(c => c.GetNewFilename(new List { episodes[2] }, "SeriesTitle2", It.IsAny())) + .Returns("Title2"); + + //Act + var totalItems = 0; + var misnamedEpisodes = mocker.Resolve().MisnamedFiles(1, 10, out totalItems); + + //Assert + misnamedEpisodes.Should().HaveCount(0); + } + } +} diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 678f753ca..b82f2f874 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -89,6 +89,7 @@ + diff --git a/NzbDrone.Core.Test/QualityProfileTest.cs b/NzbDrone.Core.Test/QualityProfileTest.cs index b1973c7c0..10cf89eaf 100644 --- a/NzbDrone.Core.Test/QualityProfileTest.cs +++ b/NzbDrone.Core.Test/QualityProfileTest.cs @@ -1,7 +1,6 @@ // ReSharper disable RedundantUsingDirective using System; using System.Collections.Generic; -using System.Linq; using AutoMoq; using FizzWare.NBuilder; using FluentAssertions; diff --git a/NzbDrone.Core.Test/SearchJobTest.cs b/NzbDrone.Core.Test/SearchJobTest.cs index 215dcd399..0e06c85f0 100644 --- a/NzbDrone.Core.Test/SearchJobTest.cs +++ b/NzbDrone.Core.Test/SearchJobTest.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using AutoMoq; using Moq; diff --git a/NzbDrone.Core.Test/SeriesSearchJobTest.cs b/NzbDrone.Core.Test/SeriesSearchJobTest.cs index 20a5ac6d4..0f64beef3 100644 --- a/NzbDrone.Core.Test/SeriesSearchJobTest.cs +++ b/NzbDrone.Core.Test/SeriesSearchJobTest.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using AutoMoq; using FizzWare.NBuilder; using FluentAssertions; diff --git a/NzbDrone.Core/Datastore/PetaDbProviderFactory.cs b/NzbDrone.Core/Datastore/PetaDbProviderFactory.cs index 593f0c6fa..c6e1cc426 100644 --- a/NzbDrone.Core/Datastore/PetaDbProviderFactory.cs +++ b/NzbDrone.Core/Datastore/PetaDbProviderFactory.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Data.Common; using System.Data.SqlServerCe; -using System.Linq; using System.Text; using MvcMiniProfiler.Data; diff --git a/NzbDrone.Core/Fluent.cs b/NzbDrone.Core/Fluent.cs index f72eef471..5b06b482d 100644 --- a/NzbDrone.Core/Fluent.cs +++ b/NzbDrone.Core/Fluent.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core diff --git a/NzbDrone.Core/Model/JobQueueItem.cs b/NzbDrone.Core/Model/JobQueueItem.cs index 71322190f..93f6bfeab 100644 --- a/NzbDrone.Core/Model/JobQueueItem.cs +++ b/NzbDrone.Core/Model/JobQueueItem.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model diff --git a/NzbDrone.Core/Model/MisnamedEpisodeModel.cs b/NzbDrone.Core/Model/MisnamedEpisodeModel.cs new file mode 100644 index 000000000..8697f6754 --- /dev/null +++ b/NzbDrone.Core/Model/MisnamedEpisodeModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NzbDrone.Core.Model +{ + public class MisnamedEpisodeModel + { + public int EpisodeFileId { get; set; } + public int SeriesId { get; set; } + public string SeriesTitle { get; set; } + public string CurrentName { get; set; } + public string ProperName { get; set; } + } +} diff --git a/NzbDrone.Core/Model/SabnzbdCategoryModel.cs b/NzbDrone.Core/Model/SabnzbdCategoryModel.cs index cf3cf34dd..e572c8f18 100644 --- a/NzbDrone.Core/Model/SabnzbdCategoryModel.cs +++ b/NzbDrone.Core/Model/SabnzbdCategoryModel.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model diff --git a/NzbDrone.Core/Model/Search/SearchModel.cs b/NzbDrone.Core/Model/Search/SearchModel.cs index 85520b106..a4847ac1c 100644 --- a/NzbDrone.Core/Model/Search/SearchModel.cs +++ b/NzbDrone.Core/Model/Search/SearchModel.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Search diff --git a/NzbDrone.Core/Model/Search/SearchType.cs b/NzbDrone.Core/Model/Search/SearchType.cs index 6a9666da7..e9d2f0dbf 100644 --- a/NzbDrone.Core/Model/Search/SearchType.cs +++ b/NzbDrone.Core/Model/Search/SearchType.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Search diff --git a/NzbDrone.Core/Model/Xbmc/ActionType.cs b/NzbDrone.Core/Model/Xbmc/ActionType.cs index 86ed9a390..3dd6a6c19 100644 --- a/NzbDrone.Core/Model/Xbmc/ActionType.cs +++ b/NzbDrone.Core/Model/Xbmc/ActionType.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Xbmc diff --git a/NzbDrone.Core/Model/Xbmc/ActivePlayersResult.cs b/NzbDrone.Core/Model/Xbmc/ActivePlayersResult.cs index f2a293964..5c00c296b 100644 --- a/NzbDrone.Core/Model/Xbmc/ActivePlayersResult.cs +++ b/NzbDrone.Core/Model/Xbmc/ActivePlayersResult.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Xbmc diff --git a/NzbDrone.Core/Model/Xbmc/Command.cs b/NzbDrone.Core/Model/Xbmc/Command.cs index c2987b3c4..c4c5a2d7b 100644 --- a/NzbDrone.Core/Model/Xbmc/Command.cs +++ b/NzbDrone.Core/Model/Xbmc/Command.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Xbmc diff --git a/NzbDrone.Core/Model/Xbmc/ErrorResult.cs b/NzbDrone.Core/Model/Xbmc/ErrorResult.cs index 8fea7df9c..605157773 100644 --- a/NzbDrone.Core/Model/Xbmc/ErrorResult.cs +++ b/NzbDrone.Core/Model/Xbmc/ErrorResult.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Xbmc diff --git a/NzbDrone.Core/Model/Xbmc/IconType.cs b/NzbDrone.Core/Model/Xbmc/IconType.cs index 090271028..f6ec678fa 100644 --- a/NzbDrone.Core/Model/Xbmc/IconType.cs +++ b/NzbDrone.Core/Model/Xbmc/IconType.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Xbmc diff --git a/NzbDrone.Core/Model/Xbmc/Params.cs b/NzbDrone.Core/Model/Xbmc/Params.cs index d867c1f0b..c8d220c43 100644 --- a/NzbDrone.Core/Model/Xbmc/Params.cs +++ b/NzbDrone.Core/Model/Xbmc/Params.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Xbmc diff --git a/NzbDrone.Core/Model/Xbmc/TvShow.cs b/NzbDrone.Core/Model/Xbmc/TvShow.cs index 35f44251c..2ec968d61 100644 --- a/NzbDrone.Core/Model/Xbmc/TvShow.cs +++ b/NzbDrone.Core/Model/Xbmc/TvShow.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Xbmc diff --git a/NzbDrone.Core/Model/Xbmc/TvShowResult.cs b/NzbDrone.Core/Model/Xbmc/TvShowResult.cs index 98c7af800..0a3ea3b3e 100644 --- a/NzbDrone.Core/Model/Xbmc/TvShowResult.cs +++ b/NzbDrone.Core/Model/Xbmc/TvShowResult.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Xbmc diff --git a/NzbDrone.Core/Model/Xbmc/VersionResult.cs b/NzbDrone.Core/Model/Xbmc/VersionResult.cs index e7eab621d..c707e3866 100644 --- a/NzbDrone.Core/Model/Xbmc/VersionResult.cs +++ b/NzbDrone.Core/Model/Xbmc/VersionResult.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace NzbDrone.Core.Model.Xbmc diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index be252641d..374b85aba 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -182,6 +182,7 @@ + @@ -191,6 +192,7 @@ + @@ -206,6 +208,7 @@ + diff --git a/NzbDrone.Core/Providers/Core/DiskProvider.cs b/NzbDrone.Core/Providers/Core/DiskProvider.cs index 3a22a4328..be81eebea 100644 --- a/NzbDrone.Core/Providers/Core/DiskProvider.cs +++ b/NzbDrone.Core/Providers/Core/DiskProvider.cs @@ -1,7 +1,7 @@ using System; -using System.Linq; using System.Collections.Generic; using System.IO; +using System.Linq; namespace NzbDrone.Core.Providers.Core { diff --git a/NzbDrone.Core/Providers/Core/UdpProvider.cs b/NzbDrone.Core/Providers/Core/UdpProvider.cs index 73a8a8903..d8955293e 100644 --- a/NzbDrone.Core/Providers/Core/UdpProvider.cs +++ b/NzbDrone.Core/Providers/Core/UdpProvider.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; diff --git a/NzbDrone.Core/Providers/EpisodeProvider.cs b/NzbDrone.Core/Providers/EpisodeProvider.cs index 681d5e404..50b2a319a 100644 --- a/NzbDrone.Core/Providers/EpisodeProvider.cs +++ b/NzbDrone.Core/Providers/EpisodeProvider.cs @@ -175,6 +175,15 @@ namespace NzbDrone.Core.Providers return AttachSeries(_database.Fetch("WHERE EpisodeFileId = @0", episodeFileId)); } + public virtual IList EpisodesWithFiles() + { + var episodes = _database.Fetch(@"SELECT Episodes.*, Series.Title as SeriesTitle, EpisodeFiles.* FROM Episodes + INNER JOIN Series ON Episodes.SeriesId = Series.SeriesId + INNER JOIN EpisodeFiles ON Episodes.EpisodeFileId = EpisodeFiles.EpisodeFileId"); + + return episodes; + } + public virtual void RefreshEpisodeInfo(Series series) { Logger.Info("Starting episode info refresh for series: {0}", series.Title.WithDefault(series.SeriesId)); diff --git a/NzbDrone.Core/Providers/Indexer/IndexerBase.cs b/NzbDrone.Core/Providers/Indexer/IndexerBase.cs index 39c3bd041..cdedde253 100644 --- a/NzbDrone.Core/Providers/Indexer/IndexerBase.cs +++ b/NzbDrone.Core/Providers/Indexer/IndexerBase.cs @@ -1,6 +1,6 @@ using System; -using System.Linq; using System.Collections.Generic; +using System.Linq; using System.Net; using System.ServiceModel.Syndication; using System.Text.RegularExpressions; diff --git a/NzbDrone.Core/Providers/Jobs/EpisodeSearchJob.cs b/NzbDrone.Core/Providers/Jobs/EpisodeSearchJob.cs index ea02abcf4..97e2baf24 100644 --- a/NzbDrone.Core/Providers/Jobs/EpisodeSearchJob.cs +++ b/NzbDrone.Core/Providers/Jobs/EpisodeSearchJob.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using NLog; using Ninject; using NzbDrone.Core.Model; diff --git a/NzbDrone.Core/Providers/Jobs/SeriesSearchJob.cs b/NzbDrone.Core/Providers/Jobs/SeriesSearchJob.cs index e5dd26b2d..2de0d0324 100644 --- a/NzbDrone.Core/Providers/Jobs/SeriesSearchJob.cs +++ b/NzbDrone.Core/Providers/Jobs/SeriesSearchJob.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using NLog; using NzbDrone.Core.Model; using NzbDrone.Core.Model.Notification; diff --git a/NzbDrone.Core/Providers/MisnamedProvider.cs b/NzbDrone.Core/Providers/MisnamedProvider.cs new file mode 100644 index 000000000..efc562069 --- /dev/null +++ b/NzbDrone.Core/Providers/MisnamedProvider.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Diagnostics; +using NLog; +using NzbDrone.Core.Model; +using NzbDrone.Core.Repository; + +namespace NzbDrone.Core.Providers +{ + public class MisnamedProvider + { + private readonly MediaFileProvider _mediaFileProvider; + private readonly EpisodeProvider _episodeProvider; + + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public MisnamedProvider(MediaFileProvider mediaFileProvider, EpisodeProvider episodeProvider) + { + _mediaFileProvider = mediaFileProvider; + _episodeProvider = episodeProvider; + } + + public virtual List MisnamedFiles(int pageNumber, int pageSize, out int totalItems) + { + var misnamedFiles = new List(); + + var episodesWithFiles = _episodeProvider.EpisodesWithFiles().GroupBy(e => e.EpisodeFileId).ToList(); + totalItems = episodesWithFiles.Count(); + + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + var misnamedFilesSelect = episodesWithFiles.AsParallel().Where( + w => + w.First().EpisodeFile.Path != + _mediaFileProvider.GetNewFilename(w.Select(e => e).ToList(), w.First().SeriesTitle, + w.First().EpisodeFile.Quality)).Skip(Math.Max(pageSize * (pageNumber - 1), 0)).Take(pageSize); + + //Process the episodes + misnamedFilesSelect.AsParallel().ForAll(f => + { + var episodes = f.Select(e => e).ToList(); + var firstEpisode = episodes[0]; + var properName = _mediaFileProvider.GetNewFilename(episodes, + firstEpisode.SeriesTitle, + firstEpisode.EpisodeFile.Quality); + + var currentName = Path.GetFileNameWithoutExtension(firstEpisode.EpisodeFile.Path); + + if (properName != currentName) + { + misnamedFiles.Add(new MisnamedEpisodeModel + { + CurrentName = currentName, + EpisodeFileId = firstEpisode.EpisodeFileId, + ProperName = properName, + SeriesId = firstEpisode.SeriesId, + SeriesTitle = firstEpisode.SeriesTitle + }); + } + }); + + stopwatch.Stop(); + return misnamedFiles.OrderBy(e => e.SeriesTitle).ToList(); + } + } +} diff --git a/NzbDrone.Core/Providers/Xbmc/EventClientProvider.cs b/NzbDrone.Core/Providers/Xbmc/EventClientProvider.cs index a9d93a7cd..7571f8cff 100644 --- a/NzbDrone.Core/Providers/Xbmc/EventClientProvider.cs +++ b/NzbDrone.Core/Providers/Xbmc/EventClientProvider.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using Ninject; using NzbDrone.Core.Providers.Core; diff --git a/NzbDrone.Core/Repository/Episode.cs b/NzbDrone.Core/Repository/Episode.cs index 8def90bc1..5c0e4b06c 100644 --- a/NzbDrone.Core/Repository/Episode.cs +++ b/NzbDrone.Core/Repository/Episode.cs @@ -59,6 +59,9 @@ namespace NzbDrone.Core.Repository [ResultColumn] public EpisodeFile EpisodeFile { get; set; } + [ResultColumn] + public string SeriesTitle { get; set; } + public override string ToString() { string seriesTitle = Series == null ? "[NULL]" : Series.Title; diff --git a/NzbDrone.Core/Repository/Quality/QualityProfile.cs b/NzbDrone.Core/Repository/Quality/QualityProfile.cs index fcec6e153..cb7571630 100644 --- a/NzbDrone.Core/Repository/Quality/QualityProfile.cs +++ b/NzbDrone.Core/Repository/Quality/QualityProfile.cs @@ -1,8 +1,8 @@ using System; -using System.Linq; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; +using System.Linq; using PetaPoco; namespace NzbDrone.Core.Repository.Quality diff --git a/NzbDrone.Web/Controllers/AddSeriesController.cs b/NzbDrone.Web/Controllers/AddSeriesController.cs index e7fd3607a..72ec764a3 100644 --- a/NzbDrone.Web/Controllers/AddSeriesController.cs +++ b/NzbDrone.Web/Controllers/AddSeriesController.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.IO; -using System.Web.Mvc; using System.Linq; +using System.Web.Mvc; using NLog; using NzbDrone.Core.Helpers; using NzbDrone.Core.Providers; diff --git a/NzbDrone.Web/Controllers/CommandController.cs b/NzbDrone.Web/Controllers/CommandController.cs index 0dbfb58a0..520609b21 100644 --- a/NzbDrone.Web/Controllers/CommandController.cs +++ b/NzbDrone.Web/Controllers/CommandController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; using System.Web.Mvc; using NzbDrone.Core.Model; diff --git a/NzbDrone.Web/Controllers/DirectoryController.cs b/NzbDrone.Web/Controllers/DirectoryController.cs index c5ad3f8f2..a9d598d83 100644 --- a/NzbDrone.Web/Controllers/DirectoryController.cs +++ b/NzbDrone.Web/Controllers/DirectoryController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; using System.Web.Helpers; using System.Web.Mvc; diff --git a/NzbDrone.Web/Controllers/HealthController.cs b/NzbDrone.Web/Controllers/HealthController.cs index 9ae802294..6988a2ede 100644 --- a/NzbDrone.Web/Controllers/HealthController.cs +++ b/NzbDrone.Web/Controllers/HealthController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; using System.Web.Mvc; diff --git a/NzbDrone.Web/Controllers/MisnamedController.cs b/NzbDrone.Web/Controllers/MisnamedController.cs new file mode 100644 index 000000000..9add4493a --- /dev/null +++ b/NzbDrone.Web/Controllers/MisnamedController.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using NzbDrone.Core.Providers; +using NzbDrone.Web.Models; +using Telerik.Web.Mvc; + +namespace NzbDrone.Web.Controllers +{ + public class MisnamedController : Controller + { + private readonly MisnamedProvider _misnamedProvider; + + public MisnamedController(MisnamedProvider misnamedProvider) + { + _misnamedProvider = misnamedProvider; + } + + public ActionResult Index() + { + return View(); + } + + [GridAction(EnableCustomBinding = true)] + public ActionResult _AjaxBinding(GridCommand gridCommand) + { + var totalItems = 0; + + var misnamed = _misnamedProvider.MisnamedFiles(gridCommand.Page, gridCommand.PageSize, out totalItems); + + return View(new GridModel{ Data = misnamed, Total = totalItems }); + } + } +} diff --git a/NzbDrone.Web/Controllers/StreamController.cs b/NzbDrone.Web/Controllers/StreamController.cs index 03085c6ce..854c4b298 100644 --- a/NzbDrone.Web/Controllers/StreamController.cs +++ b/NzbDrone.Web/Controllers/StreamController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; using System.Web.Mvc; diff --git a/NzbDrone.Web/Controllers/SystemController.cs b/NzbDrone.Web/Controllers/SystemController.cs index 5fc6723ca..ba92bd9bb 100644 --- a/NzbDrone.Web/Controllers/SystemController.cs +++ b/NzbDrone.Web/Controllers/SystemController.cs @@ -1,7 +1,7 @@ using System; -using System.Linq; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Web.Mvc; using NzbDrone.Core.Helpers; using NzbDrone.Core.Model; diff --git a/NzbDrone.Web/Global.asax.cs b/NzbDrone.Web/Global.asax.cs index 7b7d688be..0c08f1d99 100644 --- a/NzbDrone.Web/Global.asax.cs +++ b/NzbDrone.Web/Global.asax.cs @@ -1,6 +1,6 @@ using System; -using System.Linq; using System.Data.Common; +using System.Linq; using System.Reflection; using System.Threading; using System.Web; diff --git a/NzbDrone.Web/Helpers/DescriptionExtension.cs b/NzbDrone.Web/Helpers/DescriptionExtension.cs index 658397e17..2b1b8974f 100644 --- a/NzbDrone.Web/Helpers/DescriptionExtension.cs +++ b/NzbDrone.Web/Helpers/DescriptionExtension.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Linq; using System.Linq.Expressions; using System.Web; using System.Web.Mvc; diff --git a/NzbDrone.Web/Helpers/ValueExtension.cs b/NzbDrone.Web/Helpers/ValueExtension.cs index e6330d24e..5c3f6ec6f 100644 --- a/NzbDrone.Web/Helpers/ValueExtension.cs +++ b/NzbDrone.Web/Helpers/ValueExtension.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Linq; using System.Linq.Expressions; using System.Web; using System.Web.Mvc; diff --git a/NzbDrone.Web/Models/JobQueueItemModel.cs b/NzbDrone.Web/Models/JobQueueItemModel.cs index 92f196714..ad93a0fed 100644 --- a/NzbDrone.Web/Models/JobQueueItemModel.cs +++ b/NzbDrone.Web/Models/JobQueueItemModel.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; namespace NzbDrone.Web.Models diff --git a/NzbDrone.Web/Models/MissingEpisodeModel.cs b/NzbDrone.Web/Models/MissingEpisodeModel.cs index 492b440e5..95ec9ff3d 100644 --- a/NzbDrone.Web/Models/MissingEpisodeModel.cs +++ b/NzbDrone.Web/Models/MissingEpisodeModel.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; namespace NzbDrone.Web.Models diff --git a/NzbDrone.Web/Models/PendingProcessingModel.cs b/NzbDrone.Web/Models/PendingProcessingModel.cs index 8d9718f84..ff0626da8 100644 --- a/NzbDrone.Web/Models/PendingProcessingModel.cs +++ b/NzbDrone.Web/Models/PendingProcessingModel.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; namespace NzbDrone.Web.Models diff --git a/NzbDrone.Web/Models/QualityTypeModel.cs b/NzbDrone.Web/Models/QualityTypeModel.cs index 357395ddf..7f6e0a958 100644 --- a/NzbDrone.Web/Models/QualityTypeModel.cs +++ b/NzbDrone.Web/Models/QualityTypeModel.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; using NzbDrone.Core.Repository.Quality; diff --git a/NzbDrone.Web/Models/RootDirModel.cs b/NzbDrone.Web/Models/RootDirModel.cs index 3df627585..1072b3412 100644 --- a/NzbDrone.Web/Models/RootDirModel.cs +++ b/NzbDrone.Web/Models/RootDirModel.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; using System.Web.Mvc; diff --git a/NzbDrone.Web/Models/SeasonEditModel.cs b/NzbDrone.Web/Models/SeasonEditModel.cs index 4d3ea8c65..cbf14a8d6 100644 --- a/NzbDrone.Web/Models/SeasonEditModel.cs +++ b/NzbDrone.Web/Models/SeasonEditModel.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Web; namespace NzbDrone.Web.Models diff --git a/NzbDrone.Web/Models/SeriesModel.cs b/NzbDrone.Web/Models/SeriesModel.cs index be1111df2..66d3d18d8 100644 --- a/NzbDrone.Web/Models/SeriesModel.cs +++ b/NzbDrone.Web/Models/SeriesModel.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Linq; using System.Web; using NzbDrone.Core.Repository; diff --git a/NzbDrone.Web/NzbDrone.Web.csproj b/NzbDrone.Web/NzbDrone.Web.csproj index 4cc76e02d..286cda4f6 100644 --- a/NzbDrone.Web/NzbDrone.Web.csproj +++ b/NzbDrone.Web/NzbDrone.Web.csproj @@ -154,6 +154,7 @@ + @@ -351,6 +352,9 @@ + + +