From 4d3ba62e5db8686fb4a9679f84b75c9410238be4 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 5 Jun 2011 22:23:28 -0700 Subject: [PATCH] Episode renaming implemented on the Series/Details page. --- NzbDrone.Core.Test/RenameProviderTest.cs | 120 ++----------- NzbDrone.Core/CentralDispatch.cs | 1 + NzbDrone.Core/NzbDrone.Core.csproj | 1 + .../Providers/Jobs/RenameEpisodeJob.cs | 35 ++++ NzbDrone.Core/Providers/RenameProvider.cs | 168 ++---------------- NzbDrone.Web/Controllers/EpisodeController.cs | 5 + NzbDrone.Web/Controllers/SeriesController.cs | 26 --- NzbDrone.Web/Views/Series/Details.cshtml | 18 +- NzbDrone.Web/Views/Series/SubMenu.cshtml | 1 - 9 files changed, 90 insertions(+), 285 deletions(-) create mode 100644 NzbDrone.Core/Providers/Jobs/RenameEpisodeJob.cs diff --git a/NzbDrone.Core.Test/RenameProviderTest.cs b/NzbDrone.Core.Test/RenameProviderTest.cs index f82e09876..7b8038cb1 100644 --- a/NzbDrone.Core.Test/RenameProviderTest.cs +++ b/NzbDrone.Core.Test/RenameProviderTest.cs @@ -34,11 +34,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.NumberStyle).Returns(2); fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(false); - var series = Builder.CreateNew().With(s => s.Title = "South Park").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -47,17 +44,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "City Sushi") .With(e => e.SeasonNumber = 15) .With(e => e.EpisodeNumber = 6) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List {episode}); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "South Park"); //Assert Assert.AreEqual("South Park - S15E06 - City Sushi [HDTV]", result); @@ -77,11 +70,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.NumberStyle).Returns(0); fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(false); - var series = Builder.CreateNew().With(s => s.Title = "South Park").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -90,17 +80,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "City Sushi") .With(e => e.SeasonNumber = 15) .With(e => e.EpisodeNumber = 6) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episode }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "South Park"); //Assert Assert.AreEqual("15x06 - City Sushi [HDTV]", result); @@ -120,11 +106,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.NumberStyle).Returns(1); fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(false); - var series = Builder.CreateNew().With(s => s.Title = "South Park").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -133,17 +116,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "City Sushi") .With(e => e.SeasonNumber = 5) .With(e => e.EpisodeNumber = 6) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episode }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "South Park"); //Assert Assert.AreEqual("South Park 05x06 [HDTV]", result); @@ -163,11 +142,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.NumberStyle).Returns(3); fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(false); - var series = Builder.CreateNew().With(s => s.Title = "South Park").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -176,17 +152,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "City Sushi") .With(e => e.SeasonNumber = 5) .With(e => e.EpisodeNumber = 6) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episode }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "South Park"); //Assert Assert.AreEqual("South Park s05e06", result); @@ -206,11 +178,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.NumberStyle).Returns(3); fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(true); - var series = Builder.CreateNew().With(s => s.Title = "South Park").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -219,17 +188,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "City Sushi") .With(e => e.SeasonNumber = 5) .With(e => e.EpisodeNumber = 6) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episode }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "South Park"); //Assert Assert.AreEqual("South.Park.s05e06.City.Sushi", result); @@ -249,11 +214,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.NumberStyle).Returns(3); fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(true); - var series = Builder.CreateNew().With(s => s.Title = "South Park").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -262,17 +224,15 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "City Sushi") .With(e => e.SeasonNumber = 5) .With(e => e.EpisodeNumber = 6) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episode }); var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "South Park"); //Assert Assert.AreEqual("South.Park.-.s05e06.-.City.Sushi.[HDTV]", result); @@ -292,11 +252,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.NumberStyle).Returns(2); fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(false); - var series = Builder.CreateNew().With(s => s.Title = "South Park").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -305,17 +262,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "City Sushi") .With(e => e.SeasonNumber = 15) .With(e => e.EpisodeNumber = 6) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episode }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "South Park"); //Assert Assert.AreEqual("S15E06", result); @@ -336,11 +289,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(false); fakeConfig.SetupGet(c => c.MultiEpisodeStyle).Returns(3); - var series = Builder.CreateNew().With(s => s.Title = "The Mentalist").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -349,7 +299,6 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (1)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 23) - .With(e => e.SeriesId = series.SeriesId) .Build(); var episodeTwo = Builder.CreateNew() @@ -357,17 +306,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (2)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 24) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episodeOne, episodeTwo }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "The Mentalist"); //Assert Assert.AreEqual("The Mentalist - S03E23-E24 - Strawberries and Cream (1) + Strawberries and Cream (2) [HDTV]", result); @@ -388,11 +333,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(false); fakeConfig.SetupGet(c => c.MultiEpisodeStyle).Returns(2); - var series = Builder.CreateNew().With(s => s.Title = "The Mentalist").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -401,7 +343,6 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (1)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 23) - .With(e => e.SeriesId = series.SeriesId) .Build(); var episodeTwo = Builder.CreateNew() @@ -409,17 +350,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (2)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 24) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episodeOne, episodeTwo }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "The Mentalist"); //Assert Assert.AreEqual("3x23x24 - Strawberries and Cream (1) + Strawberries and Cream (2) [HDTV]", result); @@ -440,11 +377,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(false); fakeConfig.SetupGet(c => c.MultiEpisodeStyle).Returns(2); - var series = Builder.CreateNew().With(s => s.Title = "The Mentalist").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -453,7 +387,6 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (1)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 23) - .With(e => e.SeriesId = series.SeriesId) .Build(); var episodeTwo = Builder.CreateNew() @@ -461,17 +394,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (2)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 24) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episodeOne, episodeTwo }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "The Mentalist"); //Assert Assert.AreEqual("3x23x24 Strawberries and Cream (1) + Strawberries and Cream (2) [HDTV]", result); @@ -492,11 +421,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(true); fakeConfig.SetupGet(c => c.MultiEpisodeStyle).Returns(1); - var series = Builder.CreateNew().With(s => s.Title = "The Mentalist").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -505,7 +431,6 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (1)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 23) - .With(e => e.SeriesId = series.SeriesId) .Build(); var episodeTwo = Builder.CreateNew() @@ -513,17 +438,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (2)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 24) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episodeOne, episodeTwo }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "The Mentalist"); //Assert Assert.AreEqual("The.Mentalist.s03e23.s03e24.Strawberries.and.Cream.(1).+.Strawberries.and.Cream.(2)", result); @@ -544,11 +465,9 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(true); fakeConfig.SetupGet(c => c.MultiEpisodeStyle).Returns(0); - var series = Builder.CreateNew().With(s => s.Title = "The Mentalist").Build(); var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -557,7 +476,6 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (1)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 23) - .With(e => e.SeriesId = series.SeriesId) .Build(); var episodeTwo = Builder.CreateNew() @@ -565,17 +483,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (2)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 24) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episodeOne, episodeTwo }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "The Mentalist"); //Assert Assert.AreEqual("The.Mentalist.-.S03E23-24", result); @@ -596,11 +510,8 @@ namespace NzbDrone.Core.Test fakeConfig.SetupGet(c => c.ReplaceSpaces).Returns(true); fakeConfig.SetupGet(c => c.MultiEpisodeStyle).Returns(2); - var series = Builder.CreateNew().With(s => s.Title = "The Mentalist").Build(); - var episodeFile = Builder.CreateNew() .With(e => e.EpisodeFileId = 12345) - .With(e => e.SeriesId = series.SeriesId) .With(e => e.Quality = QualityTypes.HDTV) .Build(); @@ -609,7 +520,6 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (1)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 23) - .With(e => e.SeriesId = series.SeriesId) .Build(); var episodeTwo = Builder.CreateNew() @@ -617,17 +527,13 @@ namespace NzbDrone.Core.Test .With(e => e.Title = "Strawberries and Cream (2)") .With(e => e.SeasonNumber = 3) .With(e => e.EpisodeNumber = 24) - .With(e => e.SeriesId = series.SeriesId) .Build(); var fakeEpisodeProvider = mocker.GetMock(); fakeEpisodeProvider.Setup(m => m.EpisodesByFileId(12345)).Returns(new List { episodeOne, episodeTwo }); - var fakeSeriesProvider = mocker.GetMock(); - fakeSeriesProvider.Setup(m => m.GetSeries(series.SeriesId)).Returns(series); - //Act - string result = mocker.Resolve().GetNewFilename(episodeFile); + string result = mocker.Resolve().GetNewFilename(episodeFile, "The Mentalist"); //Assert Assert.AreEqual("3x23x24", result); diff --git a/NzbDrone.Core/CentralDispatch.cs b/NzbDrone.Core/CentralDispatch.cs index 89fa5766c..2e9346e63 100644 --- a/NzbDrone.Core/CentralDispatch.cs +++ b/NzbDrone.Core/CentralDispatch.cs @@ -121,6 +121,7 @@ namespace NzbDrone.Core _kernel.Bind().To().InTransientScope(); _kernel.Bind().To().InTransientScope(); _kernel.Bind().To().InTransientScope(); + _kernel.Bind().To().InTransientScope(); _kernel.Get().Initialize(); _kernel.Get().StartTimer(30); diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 69eff6d93..6c3872fce 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -184,6 +184,7 @@ + diff --git a/NzbDrone.Core/Providers/Jobs/RenameEpisodeJob.cs b/NzbDrone.Core/Providers/Jobs/RenameEpisodeJob.cs new file mode 100644 index 000000000..bf926531c --- /dev/null +++ b/NzbDrone.Core/Providers/Jobs/RenameEpisodeJob.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; +using System.Linq; +using NLog; +using NzbDrone.Core.Model.Notification; + +namespace NzbDrone.Core.Providers.Jobs +{ + public class RenameEpisodeJob : IJob + { + private readonly RenameProvider _renameProvider; + + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public RenameEpisodeJob(RenameProvider renameProvider) + { + _renameProvider = renameProvider; + } + + public string Name + { + get { return "Rename Episode"; } + } + + public int DefaultInterval + { + get { return 0; } + } + + public void Start(ProgressNotification notification, int targetId) + { + _renameProvider.RenameEpisodeFile(targetId, notification); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Providers/RenameProvider.cs b/NzbDrone.Core/Providers/RenameProvider.cs index 370e32a5c..22b468823 100644 --- a/NzbDrone.Core/Providers/RenameProvider.cs +++ b/NzbDrone.Core/Providers/RenameProvider.cs @@ -1,11 +1,9 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading; using NLog; using NzbDrone.Core.Helpers; -using NzbDrone.Core.Model; +using NzbDrone.Core.Model.Notification; using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Repository; @@ -14,7 +12,6 @@ namespace NzbDrone.Core.Providers public class RenameProvider { //TODO: Remove some of these dependencies. we shouldn't have a single class with dependency on the whole app! - //TODO: Also upgrade to a job that can run on background thread. private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private readonly ConfigProvider _configProvider; private readonly DiskProvider _diskProvider; @@ -22,10 +19,6 @@ namespace NzbDrone.Core.Providers private readonly MediaFileProvider _mediaFileProvider; private readonly SeriesProvider _seriesProvider; - private readonly List _epsToRename = new List(); - - private Thread _renameThread; - public RenameProvider(SeriesProvider seriesProvider,EpisodeProvider episodeProvider, MediaFileProvider mediaFileProvider, DiskProvider diskProvider, ConfigProvider configProvider) @@ -37,160 +30,35 @@ namespace NzbDrone.Core.Providers _configProvider = configProvider; } - public virtual void RenameAll() + public virtual void RenameEpisodeFile(int episodeFileId, ProgressNotification notification) { - //Get a list of all episode files/episodes and rename them - - foreach (var episodeFile in _mediaFileProvider.GetEpisodeFiles()) - { - var series = _seriesProvider.GetSeries(episodeFile.SeriesId); - var erm = new EpisodeRenameModel { SeriesName = series.Title, Folder = series.Path }; - - if (series.SeasonFolder) - erm.Folder += Path.DirectorySeparatorChar + - EpisodeRenameHelper.GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber, - _configProvider.GetValue( - "Sorting_SeasonFolderFormat", "Season %s", - true)); - - erm.EpisodeFile = episodeFile; - _epsToRename.Add(erm); - StartRename(); - } - } - - public virtual void RenameSeries(int seriesId) - { - //Get a list of all applicable episode files/episodes and rename them - - var series = _seriesProvider.GetSeries(seriesId); - - foreach (var episodeFile in _mediaFileProvider.GetEpisodeFiles().Where(s => s.SeriesId == seriesId)) - { - var erm = new EpisodeRenameModel { SeriesName = series.Title, Folder = series.Path }; - - if (series.SeasonFolder) - erm.Folder += Path.DirectorySeparatorChar + - EpisodeRenameHelper.GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber, - _configProvider.GetValue( - "Sorting_SeasonFolderFormat", "Season %s", - true)); - - erm.EpisodeFile = episodeFile; - _epsToRename.Add(erm); - StartRename(); - } - } - - public virtual void RenameSeason(int seasonId) - { - throw new NotImplementedException(); - } - - public virtual void RenameEpisode(int episodeId) - { - //This will properly rename multi-episode files if asked to rename either of the episode - var episode = _episodeProvider.GetEpisode(episodeId); - var series = _seriesProvider.GetSeries(episode.SeriesId); - - var episodeFile = - _mediaFileProvider.GetEpisodeFiles().Where(s => s.Episodes.Contains(episode)).FirstOrDefault(); - - var erm = new EpisodeRenameModel { SeriesName = series.Title, Folder = series.Path }; - - if (series.SeasonFolder) - erm.Folder += Path.DirectorySeparatorChar + - EpisodeRenameHelper.GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber, - _configProvider.GetValue( - "Sorting_SeasonFolderFormat", "Season %s", true)); - - erm.EpisodeFile = episodeFile; - _epsToRename.Add(erm); - StartRename(); - } - - public virtual void RenameEpisodeFile(int episodeFileId, bool newDownload) - { - //This will properly rename multi-episode files if asked to rename either of the episode var episodeFile = _mediaFileProvider.GetEpisodeFile(episodeFileId); - var series = _seriesProvider.GetSeries(episodeFile.Series.SeriesId); - var erm = new EpisodeRenameModel { SeriesName = series.Title, Folder = series.Path }; - - if (series.SeasonFolder) - erm.Folder += Path.DirectorySeparatorChar + - EpisodeRenameHelper.GetSeasonFolder(episodeFile.Episodes[0].SeasonNumber, - _configProvider.GetValue( - "Sorting_SeasonFolderFormat", "Season %s", true)); - - erm.EpisodeFile = episodeFile; - _epsToRename.Add(erm); - StartRename(); - } - - private void StartRename() - { - Logger.Debug("Episode Rename Starting"); - if (_renameThread == null || !_renameThread.IsAlive) - { - Logger.Debug("Initializing background rename of episodes"); - _renameThread = new Thread(RenameProcessor) - { - Name = "RenameEpisodes", - Priority = ThreadPriority.Lowest - }; - - _renameThread.Start(); - } - else - { - Logger.Warn("Episode renaming already in progress. Ignoring request."); - } - } - - private void RenameProcessor() - { - while (_epsToRename.Count > 0) - { - var ep = _epsToRename.First(); - _epsToRename.RemoveAt(0); - RenameFile(ep); - } - } - - private void RenameFile(EpisodeRenameModel erm) - { try { - //Update EpisodeFile if successful - Logger.Debug("Renaming Episode: {0}", Path.GetFileName(erm.EpisodeFile.Path)); - var newName = EpisodeRenameHelper.GetNewName(erm); - var ext = Path.GetExtension(erm.EpisodeFile.Path); - var newFilename = erm.Folder + Path.DirectorySeparatorChar + newName + ext; + notification.CurrentMessage = String.Format("Renaming '{0}'", episodeFile.Path); - if (!_diskProvider.FolderExists(erm.Folder)) - _diskProvider.CreateDirectory(erm.Folder); + var series = _seriesProvider.GetSeries(episodeFile.SeriesId); + var folder = new FileInfo(episodeFile.Path).DirectoryName; + var newFileName = GetNewFilename(episodeFile, series.Title); + var newFile = folder + Path.DirectorySeparatorChar + newFileName; + _diskProvider.RenameFile(episodeFile.Path, newFile); - if (erm.EpisodeFile.Path == newFilename) - return; - - _diskProvider.RenameFile(erm.EpisodeFile.Path, newFilename); - erm.EpisodeFile.Path = newFilename; - _mediaFileProvider.Update(erm.EpisodeFile); - - throw new NotImplementedException("Rename File"); + notification.CurrentMessage = String.Format("Finished Renaming '{0}'", newFile); } - catch (Exception ex) + + catch (Exception e) { - Logger.DebugException(ex.Message, ex); - Logger.Warn("Unable to Rename Episode: {0}", Path.GetFileName(erm.EpisodeFile.Path)); + notification.CurrentMessage = String.Format("Failed to Rename '{0}'", episodeFile.Path); + Logger.ErrorException("An error has occurred while renaming episode: " + episodeFile.Path, e); + throw; } } - public string GetNewFilename(EpisodeFile episodeFile) + public string GetNewFilename(EpisodeFile episodeFile, string seriesName) { var episodes = _episodeProvider.EpisodesByFileId(episodeFile.EpisodeFileId); - var series = _seriesProvider.GetSeries(episodeFile.SeriesId); + //var series = _seriesProvider.GetSeries(episodeFile.SeriesId); var separatorStyle = EpisodeSortingHelper.GetSeparatorStyle(_configProvider.SeparatorStyle); var numberStyle = EpisodeSortingHelper.GetNumberStyle(_configProvider.NumberStyle); @@ -205,7 +73,7 @@ namespace NzbDrone.Core.Providers { if (useSeriesName) { - title += series.Title; + title += seriesName; title += separatorStyle.Pattern; } @@ -233,7 +101,7 @@ namespace NzbDrone.Core.Providers if (useSeriesName) { - title += series.Title; + title += seriesName; title += separatorStyle.Pattern; } diff --git a/NzbDrone.Web/Controllers/EpisodeController.cs b/NzbDrone.Web/Controllers/EpisodeController.cs index d2c954fdc..5e1c4972a 100644 --- a/NzbDrone.Web/Controllers/EpisodeController.cs +++ b/NzbDrone.Web/Controllers/EpisodeController.cs @@ -27,6 +27,11 @@ namespace NzbDrone.Web.Controllers return new JsonResult { Data = "ok" }; } + public JsonResult Rename(int episodeFileId) + { + _jobProvider.QueueJob(typeof(RenameEpisodeJob), episodeFileId); + return new JsonResult { Data = "ok" }; + } } } \ No newline at end of file diff --git a/NzbDrone.Web/Controllers/SeriesController.cs b/NzbDrone.Web/Controllers/SeriesController.cs index aa1ebefc4..b89058e17 100644 --- a/NzbDrone.Web/Controllers/SeriesController.cs +++ b/NzbDrone.Web/Controllers/SeriesController.cs @@ -207,32 +207,6 @@ namespace NzbDrone.Web.Controllers return RedirectToAction("Details", new { seriesId }); } - public ActionResult RenameAll() - { - _renameProvider.RenameAll(); - return RedirectToAction("Index"); - } - - public ActionResult RenameSeries(int seriesId) - { - _renameProvider.RenameSeries(seriesId); - return RedirectToAction("Details", new { seriesId }); - } - - public ActionResult RenameSeason(int seasonId) - { - //Todo: Stay of Series Detail... AJAX? - _renameProvider.RenameSeason(seasonId); - return RedirectToAction("Index"); - } - - public ActionResult RenameEpisode(int episodeId) - { - //Todo: Stay of Series Detail... AJAX? - _renameProvider.RenameEpisode(episodeId); - return RedirectToAction("Index"); - } - private List GetSeriesModels(List seriesInDb) { var series = new List(); diff --git a/NzbDrone.Web/Views/Series/Details.cshtml b/NzbDrone.Web/Views/Series/Details.cshtml index 3d2747b53..2d03c1c66 100644 --- a/NzbDrone.Web/Views/Series/Details.cshtml +++ b/NzbDrone.Web/Views/Series/Details.cshtml @@ -65,7 +65,9 @@ columns.Bound(c => c.Quality).Width(0); columns.Bound(c => c.Status).Width(0); columns.Bound(o => o.EpisodeId).Title("") - .ClientTemplate("'); return false;\" >Search"); + .ClientTemplate("'); return false;\">Search" + + " | " + + "'); return false;\">Rename"); }) .DetailView(detailView => detailView.ClientTemplate("
<#= Overview #>
<#= Path #>
")) .ClientEvents(clientEvents => @@ -138,5 +140,19 @@ function episodeDetailExpanded(e) { $console.log("OnDetailViewExpand :: " + e.masterRow.cells[1].innerHTML); } + + var renameEpisodeUrl = '@Url.Action("Rename", "Episode")'; + + function renameEpisode(id) { + $.ajax({ + type: "POST", + url: renameEpisodeUrl, + data: jQuery.param({ episodeFileId: id }), + error: function (req, status, error) { + alert("Sorry! We could rename " + id + " at this time. " + error); + } + }); + } + } diff --git a/NzbDrone.Web/Views/Series/SubMenu.cshtml b/NzbDrone.Web/Views/Series/SubMenu.cshtml index 89cf39223..7f599b762 100644 --- a/NzbDrone.Web/Views/Series/SubMenu.cshtml +++ b/NzbDrone.Web/Views/Series/SubMenu.cshtml @@ -4,5 +4,4 @@ { items.Add().Text("Add Series").Action(c => c.Index()); items.Add().Text("Start RSS Sync").Action(c => c.RssSync()); - items.Add().Text("Rename All").Action(c => c.RenameAll()); }).Render();} \ No newline at end of file