1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-09-11 20:12:41 +02:00

New: CustomFormat Naming Token

This commit is contained in:
Qstick 2020-02-25 22:10:52 +00:00 committed by ta264
parent 50d6c5e61e
commit e986869e96
12 changed files with 114 additions and 12 deletions

View File

@ -80,7 +80,8 @@ class EditCustomFormatModalContent extends Component {
const { const {
id, id,
name name,
includeCustomFormatWhenRenaming
} = item; } = item;
return ( return (
@ -120,6 +121,18 @@ class EditCustomFormatModalContent extends Component {
onChange={onInputChange} onChange={onInputChange}
/> />
</FormGroup> </FormGroup>
<FormGroup>
<FormLabel>Include Custom Format when Renaming</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="includeCustomFormatWhenRenaming"
helpText="Include in {Custom Formats} renaming format"
{...includeCustomFormatWhenRenaming}
onChange={onInputChange}
/>
</FormGroup>
</Form> </Form>
<FieldSet legend="Conditions"> <FieldSet legend="Conditions">

View File

@ -152,6 +152,10 @@ class NamingModal extends Component {
{ token: '{Edition Tags}', example: 'IMAX' } { token: '{Edition Tags}', example: 'IMAX' }
]; ];
const customFormatTokens = [
{ token: '{Custom Formats}', example: 'Surround Sound x264' }
];
const originalTokens = [ const originalTokens = [
{ token: '{Original Title}', example: 'Movie.Title.HDTV.x264-EVOLVE' }, { token: '{Original Title}', example: 'Movie.Title.HDTV.x264-EVOLVE' },
{ token: '{Original Filename}', example: 'Movie.title.hdtv.x264-EVOLVE' } { token: '{Original Filename}', example: 'Movie.title.hdtv.x264-EVOLVE' }
@ -348,6 +352,28 @@ class NamingModal extends Component {
</div> </div>
</FieldSet> </FieldSet>
<FieldSet legend="Custom Formats">
<div className={styles.groups}>
{
customFormatTokens.map(({ token, example }) => {
return (
<NamingOption
key={token}
name={name}
value={value}
token={token}
example={example}
tokenSeparator={tokenSeparator}
tokenCase={tokenCase}
onPress={this.onOptionPress}
/>
);
}
)
}
</div>
</FieldSet>
<FieldSet legend="Original"> <FieldSet legend="Original">
<div className={styles.groups}> <div className={styles.groups}>
{ {

View File

@ -51,6 +51,9 @@ export default {
isSchemaPopulated: false, isSchemaPopulated: false,
isFetching: false, isFetching: false,
isPopulated: false, isPopulated: false,
schema: {
includeCustomFormatWhenRenaming: false
},
error: null, error: null,
isDeleting: false, isDeleting: false,
deleteError: null, deleteError: null,

View File

@ -39,7 +39,7 @@ public void Setup()
.Build(); .Build();
Mocker.GetMock<IBuildFileNames>() Mocker.GetMock<IBuildFileNames>()
.Setup(s => s.BuildFileName(It.IsAny<Movie>(), It.IsAny<MovieFile>(), null)) .Setup(s => s.BuildFileName(It.IsAny<Movie>(), It.IsAny<MovieFile>(), null, null))
.Returns("File Name"); .Returns("File Name");
Mocker.GetMock<IBuildFileNames>() Mocker.GetMock<IBuildFileNames>()

View File

@ -1,7 +1,9 @@
using System.Collections.Generic;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
using NzbDrone.Core.Organizer; using NzbDrone.Core.Organizer;
@ -36,6 +38,10 @@ public void Setup()
Mocker.GetMock<IQualityDefinitionService>() Mocker.GetMock<IQualityDefinitionService>()
.Setup(v => v.Get(Moq.It.IsAny<Quality>())) .Setup(v => v.Get(Moq.It.IsAny<Quality>()))
.Returns<Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v)); .Returns<Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
Mocker.GetMock<ICustomFormatService>()
.Setup(v => v.All())
.Returns(new List<CustomFormat>());
} }
[TestCase("Florence + the Machine", "Florence + the Machine")] [TestCase("Florence + the Machine", "Florence + the Machine")]

View File

@ -1,9 +1,11 @@
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.MediaInfo; using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
@ -40,6 +42,10 @@ public void Setup()
Mocker.GetMock<IQualityDefinitionService>() Mocker.GetMock<IQualityDefinitionService>()
.Setup(v => v.Get(Moq.It.IsAny<Quality>())) .Setup(v => v.Get(Moq.It.IsAny<Quality>()))
.Returns<Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v)); .Returns<Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
Mocker.GetMock<ICustomFormatService>()
.Setup(v => v.All())
.Returns(new List<CustomFormat>());
} }
private void GivenProper() private void GivenProper()

View File

@ -19,6 +19,8 @@ public CustomFormat(string name, params ICustomFormatSpecification[] specs)
public string Name { get; set; } public string Name { get; set; }
public bool IncludeCustomFormatWhenRenaming { get; set; }
public List<ICustomFormatSpecification> Specifications { get; set; } public List<ICustomFormatSpecification> Specifications { get; set; }
public override string ToString() public override string ToString()

View File

@ -33,13 +33,11 @@ public CustomFormatCalculationService(ICustomFormatService formatService,
_movieService = movieService; _movieService = movieService;
} }
public List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo) public static List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo, List<CustomFormat> allCustomFormats)
{ {
var formats = _formatService.All();
var matches = new List<CustomFormat>(); var matches = new List<CustomFormat>();
foreach (var customFormat in formats) foreach (var customFormat in allCustomFormats)
{ {
var specificationMatches = customFormat.Specifications var specificationMatches = customFormat.Specifications
.GroupBy(t => t.GetType()) .GroupBy(t => t.GetType())
@ -58,7 +56,7 @@ public List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo)
return matches; return matches;
} }
public List<CustomFormat> ParseCustomFormat(MovieFile movieFile) public static List<CustomFormat> ParseCustomFormat(MovieFile movieFile, List<CustomFormat> allCustomFormats)
{ {
var info = new ParsedMovieInfo var info = new ParsedMovieInfo
{ {
@ -78,7 +76,17 @@ public List<CustomFormat> ParseCustomFormat(MovieFile movieFile)
} }
}; };
return ParseCustomFormat(info); return ParseCustomFormat(info, allCustomFormats);
}
public List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo)
{
return ParseCustomFormat(movieInfo, _formatService.All());
}
public List<CustomFormat> ParseCustomFormat(MovieFile movieFile)
{
return ParseCustomFormat(movieFile, _formatService.All());
} }
public List<CustomFormat> ParseCustomFormat(Blacklist blacklist) public List<CustomFormat> ParseCustomFormat(Blacklist blacklist)

View File

@ -20,6 +20,8 @@ protected override void MainDbUpgrade()
Execute.WithConnection(MigrateOrderToScores); Execute.WithConnection(MigrateOrderToScores);
Delete.Column("FormatCutoff").FromTable("Profiles"); Delete.Column("FormatCutoff").FromTable("Profiles");
Alter.Table("CustomFormats").AddColumn("IncludeCustomFormatWhenRenaming").AsBoolean().WithDefaultValue(0);
} }
private void MigrateOrderToScores(IDbConnection conn, IDbTransaction tran) private void MigrateOrderToScores(IDbConnection conn, IDbTransaction tran)

View File

@ -7,6 +7,7 @@
using NLog; using NLog;
using NzbDrone.Common.EnsureThat; using NzbDrone.Common.EnsureThat;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.MediaInfo; using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
@ -16,7 +17,7 @@ namespace NzbDrone.Core.Organizer
{ {
public interface IBuildFileNames public interface IBuildFileNames
{ {
string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null); string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null, List<CustomFormat> customFormats = null);
string BuildFilePath(Movie movie, string fileName, string extension); string BuildFilePath(Movie movie, string fileName, string extension);
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec); BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
string GetMovieFolder(Movie movie, NamingConfig namingConfig = null); string GetMovieFolder(Movie movie, NamingConfig namingConfig = null);
@ -29,6 +30,7 @@ public class FileNameBuilder : IBuildFileNames
private readonly INamingConfigService _namingConfigService; private readonly INamingConfigService _namingConfigService;
private readonly IQualityDefinitionService _qualityDefinitionService; private readonly IQualityDefinitionService _qualityDefinitionService;
private readonly IUpdateMediaInfo _mediaInfoUpdater; private readonly IUpdateMediaInfo _mediaInfoUpdater;
private readonly ICustomFormatService _formatService;
private readonly Logger _logger; private readonly Logger _logger;
private static readonly Regex TitleRegex = new Regex(@"\{(?<prefix>[- ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[a-z0-9]+))?(?<suffix>[- ._)\]]*)\}", private static readonly Regex TitleRegex = new Regex(@"\{(?<prefix>[- ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[a-z0-9]+))?(?<suffix>[- ._)\]]*)\}",
@ -65,15 +67,17 @@ public class FileNameBuilder : IBuildFileNames
public FileNameBuilder(INamingConfigService namingConfigService, public FileNameBuilder(INamingConfigService namingConfigService,
IQualityDefinitionService qualityDefinitionService, IQualityDefinitionService qualityDefinitionService,
IUpdateMediaInfo mediaInfoUpdater, IUpdateMediaInfo mediaInfoUpdater,
ICustomFormatService formatService,
Logger logger) Logger logger)
{ {
_namingConfigService = namingConfigService; _namingConfigService = namingConfigService;
_qualityDefinitionService = qualityDefinitionService; _qualityDefinitionService = qualityDefinitionService;
_mediaInfoUpdater = mediaInfoUpdater; _mediaInfoUpdater = mediaInfoUpdater;
_formatService = formatService;
_logger = logger; _logger = logger;
} }
public string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null) public string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null, List<CustomFormat> customFormats = null)
{ {
if (namingConfig == null) if (namingConfig == null)
{ {
@ -97,6 +101,7 @@ public string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namin
AddMediaInfoTokens(tokenHandlers, movieFile); AddMediaInfoTokens(tokenHandlers, movieFile);
AddMovieFileTokens(tokenHandlers, movieFile); AddMovieFileTokens(tokenHandlers, movieFile);
AddTagsTokens(tokenHandlers, movieFile); AddTagsTokens(tokenHandlers, movieFile);
AddCustomFormats(tokenHandlers, movie, movieFile, customFormats);
var fileName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim(); var fileName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString()); fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString());
@ -332,6 +337,17 @@ private void AddMediaInfoTokens(Dictionary<string, Func<TokenMatch, string>> tok
m => MediaInfoFormatter.FormatVideoDynamicRange(movieFile.MediaInfo); m => MediaInfoFormatter.FormatVideoDynamicRange(movieFile.MediaInfo);
} }
private void AddCustomFormats(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Movie movie, MovieFile movieFile, List<CustomFormat> customFormats = null)
{
if (customFormats == null)
{
movieFile.Movie = movie;
customFormats = CustomFormatCalculationService.ParseCustomFormat(movieFile, _formatService.All());
}
tokenHandlers["{Custom Formats}"] = m => string.Join(" ", customFormats.Where(x => x.IncludeCustomFormatWhenRenaming));
}
private string GetLanguagesToken(string mediaInfoLanguages) private string GetLanguagesToken(string mediaInfoLanguages)
{ {
List<string> tokens = new List<string>(); List<string> tokens = new List<string>();

View File

@ -1,3 +1,5 @@
using System.Collections.Generic;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.MediaInfo; using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Core.Movies; using NzbDrone.Core.Movies;
@ -17,6 +19,7 @@ public class FileNameSampleService : IFilenameSampleService
private static MovieFile _movieFile; private static MovieFile _movieFile;
private static Movie _movie; private static Movie _movie;
private static List<CustomFormat> _customFormats;
public FileNameSampleService(IBuildFileNames buildFileNames) public FileNameSampleService(IBuildFileNames buildFileNames)
{ {
@ -55,6 +58,20 @@ public FileNameSampleService(IBuildFileNames buildFileNames)
MovieFile = _movieFile, MovieFile = _movieFile,
MovieFileId = 1, MovieFileId = 1,
}; };
_customFormats = new List<CustomFormat>
{
new CustomFormat
{
Name = "Surround Sound",
IncludeCustomFormatWhenRenaming = true
},
new CustomFormat
{
Name = "x264",
IncludeCustomFormatWhenRenaming = true
}
};
} }
public SampleResult GetMovieSample(NamingConfig nameSpec) public SampleResult GetMovieSample(NamingConfig nameSpec)
@ -76,7 +93,7 @@ private string BuildSample(Movie movie, MovieFile movieFile, NamingConfig nameSp
{ {
try try
{ {
return _buildFileNames.BuildFileName(movie, movieFile, nameSpec); return _buildFileNames.BuildFileName(movie, movieFile, nameSpec, _customFormats);
} }
catch (NamingFormatException) catch (NamingFormatException)
{ {

View File

@ -12,6 +12,7 @@ public class CustomFormatResource : RestResource
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)] [JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]
public override int Id { get; set; } public override int Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public bool IncludeCustomFormatWhenRenaming { get; set; }
public List<CustomFormatSpecificationSchema> Specifications { get; set; } public List<CustomFormatSpecificationSchema> Specifications { get; set; }
} }
@ -23,7 +24,8 @@ public static CustomFormatResource ToResource(this CustomFormat model)
{ {
Id = model.Id, Id = model.Id,
Name = model.Name, Name = model.Name,
Specifications = model.Specifications.Select(x => x.ToSchema()).ToList(), IncludeCustomFormatWhenRenaming = model.IncludeCustomFormatWhenRenaming,
Specifications = model.Specifications.Select(x => x.ToSchema()).ToList()
}; };
} }
@ -38,6 +40,7 @@ public static CustomFormat ToModel(this CustomFormatResource resource, List<ICus
{ {
Id = resource.Id, Id = resource.Id,
Name = resource.Name, Name = resource.Name,
IncludeCustomFormatWhenRenaming = resource.IncludeCustomFormatWhenRenaming,
Specifications = resource.Specifications.Select(x => MapSpecification(x, specifications)).ToList() Specifications = resource.Specifications.Select(x => MapSpecification(x, specifications)).ToList()
}; };
} }