mirror of
https://github.com/Radarr/Radarr.git
synced 2024-08-18 08:19:38 +02:00
New: CustomFormat Naming Token
This commit is contained in:
parent
50d6c5e61e
commit
e986869e96
@ -80,7 +80,8 @@ class EditCustomFormatModalContent extends Component {
|
||||
|
||||
const {
|
||||
id,
|
||||
name
|
||||
name,
|
||||
includeCustomFormatWhenRenaming
|
||||
} = item;
|
||||
|
||||
return (
|
||||
@ -120,6 +121,18 @@ class EditCustomFormatModalContent extends Component {
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</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>
|
||||
|
||||
<FieldSet legend="Conditions">
|
||||
|
@ -152,6 +152,10 @@ class NamingModal extends Component {
|
||||
{ token: '{Edition Tags}', example: 'IMAX' }
|
||||
];
|
||||
|
||||
const customFormatTokens = [
|
||||
{ token: '{Custom Formats}', example: 'Surround Sound x264' }
|
||||
];
|
||||
|
||||
const originalTokens = [
|
||||
{ token: '{Original Title}', example: 'Movie.Title.HDTV.x264-EVOLVE' },
|
||||
{ token: '{Original Filename}', example: 'Movie.title.hdtv.x264-EVOLVE' }
|
||||
@ -348,6 +352,28 @@ class NamingModal extends Component {
|
||||
</div>
|
||||
</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">
|
||||
<div className={styles.groups}>
|
||||
{
|
||||
|
@ -51,6 +51,9 @@ export default {
|
||||
isSchemaPopulated: false,
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
schema: {
|
||||
includeCustomFormatWhenRenaming: false
|
||||
},
|
||||
error: null,
|
||||
isDeleting: false,
|
||||
deleteError: null,
|
||||
|
@ -39,7 +39,7 @@ public void Setup()
|
||||
.Build();
|
||||
|
||||
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");
|
||||
|
||||
Mocker.GetMock<IBuildFileNames>()
|
||||
|
@ -1,7 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Organizer;
|
||||
@ -36,6 +38,10 @@ public void Setup()
|
||||
Mocker.GetMock<IQualityDefinitionService>()
|
||||
.Setup(v => v.Get(Moq.It.IsAny<Quality>()))
|
||||
.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")]
|
||||
|
@ -1,9 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||
using NzbDrone.Core.Movies;
|
||||
@ -40,6 +42,10 @@ public void Setup()
|
||||
Mocker.GetMock<IQualityDefinitionService>()
|
||||
.Setup(v => v.Get(Moq.It.IsAny<Quality>()))
|
||||
.Returns<Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
|
||||
|
||||
Mocker.GetMock<ICustomFormatService>()
|
||||
.Setup(v => v.All())
|
||||
.Returns(new List<CustomFormat>());
|
||||
}
|
||||
|
||||
private void GivenProper()
|
||||
|
@ -19,6 +19,8 @@ public CustomFormat(string name, params ICustomFormatSpecification[] specs)
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public bool IncludeCustomFormatWhenRenaming { get; set; }
|
||||
|
||||
public List<ICustomFormatSpecification> Specifications { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
|
@ -33,13 +33,11 @@ public CustomFormatCalculationService(ICustomFormatService formatService,
|
||||
_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>();
|
||||
|
||||
foreach (var customFormat in formats)
|
||||
foreach (var customFormat in allCustomFormats)
|
||||
{
|
||||
var specificationMatches = customFormat.Specifications
|
||||
.GroupBy(t => t.GetType())
|
||||
@ -58,7 +56,7 @@ public List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo)
|
||||
return matches;
|
||||
}
|
||||
|
||||
public List<CustomFormat> ParseCustomFormat(MovieFile movieFile)
|
||||
public static List<CustomFormat> ParseCustomFormat(MovieFile movieFile, List<CustomFormat> allCustomFormats)
|
||||
{
|
||||
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)
|
||||
|
@ -20,6 +20,8 @@ protected override void MainDbUpgrade()
|
||||
Execute.WithConnection(MigrateOrderToScores);
|
||||
|
||||
Delete.Column("FormatCutoff").FromTable("Profiles");
|
||||
|
||||
Alter.Table("CustomFormats").AddColumn("IncludeCustomFormatWhenRenaming").AsBoolean().WithDefaultValue(0);
|
||||
}
|
||||
|
||||
private void MigrateOrderToScores(IDbConnection conn, IDbTransaction tran)
|
||||
|
@ -7,6 +7,7 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnsureThat;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||
using NzbDrone.Core.Movies;
|
||||
@ -16,7 +17,7 @@ namespace NzbDrone.Core.Organizer
|
||||
{
|
||||
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);
|
||||
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
|
||||
string GetMovieFolder(Movie movie, NamingConfig namingConfig = null);
|
||||
@ -29,6 +30,7 @@ public class FileNameBuilder : IBuildFileNames
|
||||
private readonly INamingConfigService _namingConfigService;
|
||||
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||
private readonly IUpdateMediaInfo _mediaInfoUpdater;
|
||||
private readonly ICustomFormatService _formatService;
|
||||
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>[- ._)\]]*)\}",
|
||||
@ -65,15 +67,17 @@ public class FileNameBuilder : IBuildFileNames
|
||||
public FileNameBuilder(INamingConfigService namingConfigService,
|
||||
IQualityDefinitionService qualityDefinitionService,
|
||||
IUpdateMediaInfo mediaInfoUpdater,
|
||||
ICustomFormatService formatService,
|
||||
Logger logger)
|
||||
{
|
||||
_namingConfigService = namingConfigService;
|
||||
_qualityDefinitionService = qualityDefinitionService;
|
||||
_mediaInfoUpdater = mediaInfoUpdater;
|
||||
_formatService = formatService;
|
||||
_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)
|
||||
{
|
||||
@ -97,6 +101,7 @@ public string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namin
|
||||
AddMediaInfoTokens(tokenHandlers, movieFile);
|
||||
AddMovieFileTokens(tokenHandlers, movieFile);
|
||||
AddTagsTokens(tokenHandlers, movieFile);
|
||||
AddCustomFormats(tokenHandlers, movie, movieFile, customFormats);
|
||||
|
||||
var fileName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
List<string> tokens = new List<string>();
|
||||
|
@ -1,3 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||
using NzbDrone.Core.Movies;
|
||||
@ -17,6 +19,7 @@ public class FileNameSampleService : IFilenameSampleService
|
||||
|
||||
private static MovieFile _movieFile;
|
||||
private static Movie _movie;
|
||||
private static List<CustomFormat> _customFormats;
|
||||
|
||||
public FileNameSampleService(IBuildFileNames buildFileNames)
|
||||
{
|
||||
@ -55,6 +58,20 @@ public FileNameSampleService(IBuildFileNames buildFileNames)
|
||||
MovieFile = _movieFile,
|
||||
MovieFileId = 1,
|
||||
};
|
||||
|
||||
_customFormats = new List<CustomFormat>
|
||||
{
|
||||
new CustomFormat
|
||||
{
|
||||
Name = "Surround Sound",
|
||||
IncludeCustomFormatWhenRenaming = true
|
||||
},
|
||||
new CustomFormat
|
||||
{
|
||||
Name = "x264",
|
||||
IncludeCustomFormatWhenRenaming = true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public SampleResult GetMovieSample(NamingConfig nameSpec)
|
||||
@ -76,7 +93,7 @@ private string BuildSample(Movie movie, MovieFile movieFile, NamingConfig nameSp
|
||||
{
|
||||
try
|
||||
{
|
||||
return _buildFileNames.BuildFileName(movie, movieFile, nameSpec);
|
||||
return _buildFileNames.BuildFileName(movie, movieFile, nameSpec, _customFormats);
|
||||
}
|
||||
catch (NamingFormatException)
|
||||
{
|
||||
|
@ -12,6 +12,7 @@ public class CustomFormatResource : RestResource
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]
|
||||
public override int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool IncludeCustomFormatWhenRenaming { get; set; }
|
||||
public List<CustomFormatSpecificationSchema> Specifications { get; set; }
|
||||
}
|
||||
|
||||
@ -23,7 +24,8 @@ public static CustomFormatResource ToResource(this CustomFormat model)
|
||||
{
|
||||
Id = model.Id,
|
||||
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,
|
||||
Name = resource.Name,
|
||||
IncludeCustomFormatWhenRenaming = resource.IncludeCustomFormatWhenRenaming,
|
||||
Specifications = resource.Specifications.Select(x => MapSpecification(x, specifications)).ToList()
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user