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:
parent
50d6c5e61e
commit
e986869e96
@ -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">
|
||||||
|
@ -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}>
|
||||||
{
|
{
|
||||||
|
@ -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,
|
||||||
|
@ -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>()
|
||||||
|
@ -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")]
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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>();
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user