From 721767331bf7330c76019459e1d67686bba5b81a Mon Sep 17 00:00:00 2001 From: Tim Turner Date: Fri, 6 Jan 2017 19:32:19 -0500 Subject: [PATCH] Update naming management Still need to write BuildFileName() and BuildFilePath() --- src/NzbDrone.Api/Config/NamingConfigModule.cs | 16 +++- .../Config/NamingConfigResource.cs | 10 +- .../Config/NamingSampleResource.cs | 3 + .../109_add_movie_formats_to_naming_config.cs | 92 +++++++++++++++++++ src/NzbDrone.Core/NzbDrone.Core.csproj | 1 + .../Organizer/FileNameBuilder.cs | 5 +- .../Organizer/FileNameValidation.cs | 12 +++ src/NzbDrone.Core/Organizer/NamingConfig.cs | 8 +- src/UI/AddMovies/AddMoviesView.js | 4 +- .../AddMovies/SearchResultCollectionView.js | 2 +- src/UI/AddMovies/SearchResultView.js | 26 +++--- .../FileManagementViewTemplate.hbs | 4 +- .../Naming/NamingViewTemplate.hbs | 55 ++++++----- .../Partials/MovieTitleNamingPartial.hbs | 11 +++ .../Partials/ReleaseYearNamingPartial.hbs | 1 + .../Sorting/SortingViewTemplate.hbs | 8 +- 16 files changed, 202 insertions(+), 56 deletions(-) create mode 100644 src/NzbDrone.Core/Datastore/Migration/109_add_movie_formats_to_naming_config.cs create mode 100644 src/UI/Settings/MediaManagement/Naming/Partials/MovieTitleNamingPartial.hbs create mode 100644 src/UI/Settings/MediaManagement/Naming/Partials/ReleaseYearNamingPartial.hbs diff --git a/src/NzbDrone.Api/Config/NamingConfigModule.cs b/src/NzbDrone.Api/Config/NamingConfigModule.cs index 0b72e0b0c..301966406 100644 --- a/src/NzbDrone.Api/Config/NamingConfigModule.cs +++ b/src/NzbDrone.Api/Config/NamingConfigModule.cs @@ -39,6 +39,8 @@ namespace NzbDrone.Api.Config SharedValidator.RuleFor(c => c.AnimeEpisodeFormat).ValidAnimeEpisodeFormat(); SharedValidator.RuleFor(c => c.SeriesFolderFormat).ValidSeriesFolderFormat(); SharedValidator.RuleFor(c => c.SeasonFolderFormat).ValidSeasonFolderFormat(); + SharedValidator.RuleFor(c => c.StandardMovieFormat).ValidMovieFormat(); + SharedValidator.RuleFor(c => c.MovieFolderFormat).ValidMovieFolderFormat(); } private void UpdateNamingConfig(NamingConfigResource resource) @@ -54,7 +56,13 @@ namespace NzbDrone.Api.Config var nameSpec = _namingConfigService.GetConfig(); var resource = nameSpec.ToResource(); - if (resource.StandardEpisodeFormat.IsNotNullOrWhiteSpace()) + //if (resource.StandardEpisodeFormat.IsNotNullOrWhiteSpace()) + //{ + // var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec); + // basicConfig.AddToResource(resource); + //} + + if (resource.StandardMovieFormat.IsNotNullOrWhiteSpace()) { var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec); basicConfig.AddToResource(resource); @@ -118,12 +126,16 @@ namespace NzbDrone.Api.Config var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec); var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec); + //var movieSampleResult = _filenameSampleService.GetMovieSample(nameSpec); + var singleEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult); var multiEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult); var dailyEpisodeValidationResult = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult); var animeEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult); var animeMultiEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult); + //var standardMovieValidationResult = _filenameValidationService.ValidateStandardMovieFilename(movieSampleResult); + var validationFailures = new List(); validationFailures.AddIfNotNull(singleEpisodeValidationResult); @@ -132,6 +144,8 @@ namespace NzbDrone.Api.Config validationFailures.AddIfNotNull(animeEpisodeValidationResult); validationFailures.AddIfNotNull(animeMultiEpisodeValidationResult); + //validationFailures.AddIfNotNull(standardMovieValidationResult); + if (validationFailures.Any()) { throw new ValidationException(validationFailures.DistinctBy(v => v.PropertyName).ToArray()); diff --git a/src/NzbDrone.Api/Config/NamingConfigResource.cs b/src/NzbDrone.Api/Config/NamingConfigResource.cs index 39147b993..110a7d402 100644 --- a/src/NzbDrone.Api/Config/NamingConfigResource.cs +++ b/src/NzbDrone.Api/Config/NamingConfigResource.cs @@ -7,6 +7,8 @@ namespace NzbDrone.Api.Config { public bool RenameEpisodes { get; set; } public bool ReplaceIllegalCharacters { get; set; } + public string StandardMovieFormat { get; set; } + public string MovieFolderFormat { get; set; } public int MultiEpisodeStyle { get; set; } public string StandardEpisodeFormat { get; set; } public string DailyEpisodeFormat { get; set; } @@ -36,7 +38,9 @@ namespace NzbDrone.Api.Config DailyEpisodeFormat = model.DailyEpisodeFormat, AnimeEpisodeFormat = model.AnimeEpisodeFormat, SeriesFolderFormat = model.SeriesFolderFormat, - SeasonFolderFormat = model.SeasonFolderFormat + SeasonFolderFormat = model.SeasonFolderFormat, + StandardMovieFormat = model.StandardMovieFormat, + MovieFolderFormat = model.MovieFolderFormat //IncludeSeriesTitle //IncludeEpisodeTitle //IncludeQuality @@ -69,7 +73,9 @@ namespace NzbDrone.Api.Config DailyEpisodeFormat = resource.DailyEpisodeFormat, AnimeEpisodeFormat = resource.AnimeEpisodeFormat, SeriesFolderFormat = resource.SeriesFolderFormat, - SeasonFolderFormat = resource.SeasonFolderFormat + SeasonFolderFormat = resource.SeasonFolderFormat, + StandardMovieFormat = resource.StandardMovieFormat, + MovieFolderFormat = resource.MovieFolderFormat }; } } diff --git a/src/NzbDrone.Api/Config/NamingSampleResource.cs b/src/NzbDrone.Api/Config/NamingSampleResource.cs index 1f9c7f066..3430050e0 100644 --- a/src/NzbDrone.Api/Config/NamingSampleResource.cs +++ b/src/NzbDrone.Api/Config/NamingSampleResource.cs @@ -9,5 +9,8 @@ public string AnimeMultiEpisodeExample { get; set; } public string SeriesFolderExample { get; set; } public string SeasonFolderExample { get; set; } + + public string MovieExample { get; set; } + public string MovieFolderExample { get; set; } } } \ No newline at end of file diff --git a/src/NzbDrone.Core/Datastore/Migration/109_add_movie_formats_to_naming_config.cs b/src/NzbDrone.Core/Datastore/Migration/109_add_movie_formats_to_naming_config.cs new file mode 100644 index 000000000..a51232718 --- /dev/null +++ b/src/NzbDrone.Core/Datastore/Migration/109_add_movie_formats_to_naming_config.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; +using System.Data; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(109)] + public class add_movie_formats_to_naming_config : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Alter.Table("NamingConfig").AddColumn("StandardMovieFormat").AsString().Nullable(); + Alter.Table("NamingConfig").AddColumn("MovieFolderFormat").AsString().Nullable(); + + Execute.WithConnection(ConvertConfig); + } + + private void ConvertConfig(IDbConnection conn, IDbTransaction tran) + { + + using (IDbCommand namingConfigCmd = conn.CreateCommand()) + { + namingConfigCmd.Transaction = tran; + namingConfigCmd.CommandText = @"SELECT * FROM NamingConfig LIMIT 1"; + using (IDataReader namingConfigReader = namingConfigCmd.ExecuteReader()) + { + var separatorIndex = namingConfigReader.GetOrdinal("Separator"); + var includeQualityIndex = namingConfigReader.GetOrdinal("IncludeQuality"); + var replaceSpacesIndex = namingConfigReader.GetOrdinal("ReplaceSpaces"); + + while (namingConfigReader.Read()) + { + var separator = namingConfigReader.GetString(separatorIndex); + var includeQuality = namingConfigReader.GetBoolean(includeQualityIndex); + var replaceSpaces = namingConfigReader.GetBoolean(replaceSpacesIndex); + + // Output Settings + var movieTitlePattern = ""; + var movieYearPattern = "({Release Year})"; + var qualityFormat = " [{Quality Title}]"; + + if (replaceSpaces) + { + movieTitlePattern = "{Movie.Title}"; + + } + else + { + movieTitlePattern = "{Movie Title}"; + } + + movieTitlePattern += separator; + + var standardMovieFormat = string.Format("{0}{1}{2}", movieTitlePattern, + movieYearPattern, + qualityFormat); + + var movieFolderFormat = string.Format("{0}{1}", movieTitlePattern, movieYearPattern); + + if (includeQuality) + { + if (replaceSpaces) + { + qualityFormat = ".[{Quality.Title}]"; + } + + movieFolderFormat += qualityFormat; + standardMovieFormat += qualityFormat; + } + + using (IDbCommand updateCmd = conn.CreateCommand()) + { + var text = string.Format("UPDATE NamingConfig " + + "SET StandardMovieFormat = '{0}', " + + "MovieFolderFormat = '{1}'", + standardMovieFormat, + movieFolderFormat); + + updateCmd.Transaction = tran; + updateCmd.CommandText = text; + updateCmd.ExecuteNonQuery(); + } + } + } + } + } + } +} diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 14d74a9e5..8720a43ff 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -286,6 +286,7 @@ Code + diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs index 17d1f4c57..53ed08998 100644 --- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs +++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -58,6 +58,9 @@ namespace NzbDrone.Core.Organizer public static readonly Regex SeriesTitleRegex = new Regex(@"(?\{(?:Series)(?[- ._])(Clean)?Title\})", RegexOptions.Compiled | RegexOptions.IgnoreCase); + public static readonly Regex MovieTitleRegex = new Regex(@"(?\{(?:Movie)(?[- ._])(Clean)?Title\})", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex FileNameCleanupRegex = new Regex(@"([- ._])(\1)+", RegexOptions.Compiled); private static readonly Regex TrimSeparatorsRegex = new Regex(@"[- ._]$", RegexOptions.Compiled); diff --git a/src/NzbDrone.Core/Organizer/FileNameValidation.cs b/src/NzbDrone.Core/Organizer/FileNameValidation.cs index 930b8a044..c1f4ac776 100644 --- a/src/NzbDrone.Core/Organizer/FileNameValidation.cs +++ b/src/NzbDrone.Core/Organizer/FileNameValidation.cs @@ -41,6 +41,18 @@ namespace NzbDrone.Core.Organizer ruleBuilder.SetValidator(new NotEmptyValidator(null)); return ruleBuilder.SetValidator(new RegularExpressionValidator(SeasonFolderRegex)).WithMessage("Must contain season number"); } + + public static IRuleBuilderOptions ValidMovieFolderFormat(this IRuleBuilder ruleBuilder) + { + ruleBuilder.SetValidator(new NotEmptyValidator(null)); + return ruleBuilder.SetValidator(new RegularExpressionValidator(FileNameBuilder.MovieTitleRegex)).WithMessage("Must contain movie title"); + } + + public static IRuleBuilderOptions ValidMovieFormat(this IRuleBuilder ruleBuilder) + { + ruleBuilder.SetValidator(new NotEmptyValidator(null)); + return ruleBuilder.SetValidator(new RegularExpressionValidator(FileNameBuilder.MovieTitleRegex)).WithMessage("Must contain movie title"); + } } public class ValidStandardEpisodeFormatValidator : PropertyValidator diff --git a/src/NzbDrone.Core/Organizer/NamingConfig.cs b/src/NzbDrone.Core/Organizer/NamingConfig.cs index 5de62a090..2ce3c64af 100644 --- a/src/NzbDrone.Core/Organizer/NamingConfig.cs +++ b/src/NzbDrone.Core/Organizer/NamingConfig.cs @@ -1,4 +1,4 @@ -using NzbDrone.Core.Datastore; +using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Organizer { @@ -13,7 +13,9 @@ namespace NzbDrone.Core.Organizer DailyEpisodeFormat = "{Series Title} - {Air-Date} - {Episode Title} {Quality Full}", AnimeEpisodeFormat = "{Series Title} - S{season:00}E{episode:00} - {Episode Title} {Quality Full}", SeriesFolderFormat = "{Series Title}", - SeasonFolderFormat = "Season {season}" + SeasonFolderFormat = "Season {season}", + MovieFolderFormat = "{Movie Title}", + StandardMovieFormat = "{Movie Title} {Quality Full}", }; public bool RenameEpisodes { get; set; } @@ -24,5 +26,7 @@ namespace NzbDrone.Core.Organizer public string AnimeEpisodeFormat { get; set; } public string SeriesFolderFormat { get; set; } public string SeasonFolderFormat { get; set; } + public string StandardMovieFormat { get; set; } + public string MovieFolderFormat { get; set; } } } diff --git a/src/UI/AddMovies/AddMoviesView.js b/src/UI/AddMovies/AddMoviesView.js index ed4c5e2e8..ca47d5368 100644 --- a/src/UI/AddMovies/AddMoviesView.js +++ b/src/UI/AddMovies/AddMoviesView.js @@ -26,7 +26,7 @@ module.exports = Marionette.Layout.extend({ }, initialize : function(options) { - console.log(options) + console.log(options); this.isExisting = options.isExisting; this.collection = new AddMoviesCollection(); @@ -125,7 +125,7 @@ module.exports = Marionette.Layout.extend({ } else if (!this.isExisting) { - this.resultCollectionView.setExisting(options.movie.get('tmdbId')) + this.resultCollectionView.setExisting(options.movie.get('tmdbId')); /*this.collection.term = ''; this.collection.reset(); this._clearResults(); diff --git a/src/UI/AddMovies/SearchResultCollectionView.js b/src/UI/AddMovies/SearchResultCollectionView.js index 1d8c2df89..02fe1fa41 100644 --- a/src/UI/AddMovies/SearchResultCollectionView.js +++ b/src/UI/AddMovies/SearchResultCollectionView.js @@ -23,7 +23,7 @@ module.exports = Marionette.CollectionView.extend({ setExisting : function(tmdbid) { var movies = this.collection.where({ tmdbId : tmdbid }); - console.warn(movies) + console.warn(movies); //debugger; if (movies.length > 0) { this.children.findByModel(movies[0])._configureTemplateHelpers(); diff --git a/src/UI/AddMovies/SearchResultView.js b/src/UI/AddMovies/SearchResultView.js index 7a2a4a6ac..3d50e1030 100644 --- a/src/UI/AddMovies/SearchResultView.js +++ b/src/UI/AddMovies/SearchResultView.js @@ -92,14 +92,14 @@ var view = Marionette.ItemView.extend({ _configureTemplateHelpers : function() { var existingMovies = MoviesCollection.where({ tmdbId : this.model.get('tmdbId') }); - console.log(existingMovies) + console.log(existingMovies); if (existingMovies.length > 0) { this.templateHelpers.existing = existingMovies[0].toJSON(); } this.templateHelpers.profiles = Profiles.toJSON(); - console.log(this.model) - console.log(this.templateHelpers.existing) + console.log(this.model); + console.log(this.templateHelpers.existing); if (!this.model.get('isExisting')) { this.templateHelpers.rootFolders = RootFolders.toJSON(); } @@ -245,14 +245,14 @@ var view = Marionette.ItemView.extend({ options.ignoreEpisodesWithoutFiles = true; } - else if (monitor === 'latest') { - this.model.setSeasonPass(lastSeason.seasonNumber); - } + // else if (monitor === 'latest') { + // this.model.setSeasonPass(lastSeason.seasonNumber); + // } - else if (monitor === 'first') { - this.model.setSeasonPass(lastSeason.seasonNumber + 1); - this.model.setSeasonMonitored(firstSeason.seasonNumber); - } + // else if (monitor === 'first') { + // this.model.setSeasonPass(lastSeason.seasonNumber + 1); + // this.model.setSeasonMonitored(firstSeason.seasonNumber); + // } else if (monitor === 'missing') { options.ignoreEpisodesWithFiles = true; @@ -262,9 +262,9 @@ var view = Marionette.ItemView.extend({ options.ignoreEpisodesWithoutFiles = true; } - else if (monitor === 'none') { - this.model.setSeasonPass(lastSeason.seasonNumber + 1); - } + // else if (monitor === 'none') { + // this.model.setSeasonPass(lastSeason.seasonNumber + 1); + // } return options; } diff --git a/src/UI/Settings/MediaManagement/FileManagement/FileManagementViewTemplate.hbs b/src/UI/Settings/MediaManagement/FileManagement/FileManagementViewTemplate.hbs index 2a3dd5d51..6d0652fa3 100644 --- a/src/UI/Settings/MediaManagement/FileManagement/FileManagementViewTemplate.hbs +++ b/src/UI/Settings/MediaManagement/FileManagement/FileManagementViewTemplate.hbs @@ -17,7 +17,7 @@ - + @@ -39,7 +39,7 @@ - + diff --git a/src/UI/Settings/MediaManagement/Naming/NamingViewTemplate.hbs b/src/UI/Settings/MediaManagement/Naming/NamingViewTemplate.hbs index 361954d70..1b0e34c2f 100644 --- a/src/UI/Settings/MediaManagement/Naming/NamingViewTemplate.hbs +++ b/src/UI/Settings/MediaManagement/Naming/NamingViewTemplate.hbs @@ -1,8 +1,8 @@
- Episode Naming + Movie Naming
- +
@@ -18,7 +18,7 @@ - +
@@ -51,25 +51,23 @@
- +
- +
- +
-
+ {{!--
@@ -111,9 +109,9 @@
-
+
--}} -
+ {{!--
@@ -144,31 +142,32 @@
-
+ --}}
- +
- +
- +
-
+ {{!--
@@ -186,9 +185,9 @@
- + --}} -
+ {{!--
@@ -203,17 +202,17 @@
-
+ --}}
- +

-
+ {{!--
@@ -242,21 +241,21 @@

-
+
--}}
- +

-
+ {{!--

-
+
--}}
diff --git a/src/UI/Settings/MediaManagement/Naming/Partials/MovieTitleNamingPartial.hbs b/src/UI/Settings/MediaManagement/Naming/Partials/MovieTitleNamingPartial.hbs new file mode 100644 index 000000000..916416fdb --- /dev/null +++ b/src/UI/Settings/MediaManagement/Naming/Partials/MovieTitleNamingPartial.hbs @@ -0,0 +1,11 @@ + diff --git a/src/UI/Settings/MediaManagement/Naming/Partials/ReleaseYearNamingPartial.hbs b/src/UI/Settings/MediaManagement/Naming/Partials/ReleaseYearNamingPartial.hbs new file mode 100644 index 000000000..0a4153d66 --- /dev/null +++ b/src/UI/Settings/MediaManagement/Naming/Partials/ReleaseYearNamingPartial.hbs @@ -0,0 +1 @@ +
  • Release Year
  • \ No newline at end of file diff --git a/src/UI/Settings/MediaManagement/Sorting/SortingViewTemplate.hbs b/src/UI/Settings/MediaManagement/Sorting/SortingViewTemplate.hbs index c78c7393a..c0784c942 100644 --- a/src/UI/Settings/MediaManagement/Sorting/SortingViewTemplate.hbs +++ b/src/UI/Settings/MediaManagement/Sorting/SortingViewTemplate.hbs @@ -2,7 +2,7 @@ Folders
    - +
    @@ -18,7 +18,7 @@ - +
    @@ -46,7 +46,7 @@ - +
    @@ -71,7 +71,7 @@ - +