Custom File Naming complete. Final testing remains

This commit is contained in:
Robert McRackan 2021-11-02 17:05:29 -04:00
parent c837fefbdd
commit ab450c37c4
9 changed files with 233 additions and 216 deletions

View File

@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<Version>6.3.4.19</Version> <Version>6.4.0.1</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -11,42 +11,18 @@ namespace FileLiberator
{ {
public static class AudioFileStorageExt public static class AudioFileStorageExt
{ {
public class MultipartRenamer private class MultipartRenamer
{ {
private LibraryBookDto libraryBookDto { get; } private LibraryBook libraryBook { get; }
public MultipartRenamer(LibraryBook libraryBook) : this(libraryBook.ToDto()) { } internal MultipartRenamer(LibraryBook libraryBook) => this.libraryBook = libraryBook;
public MultipartRenamer(LibraryBookDto libraryBookDto) => this.libraryBookDto = libraryBookDto;
internal string MultipartFilename(AaxDecrypter.MultiConvertFileProperties props) internal string MultipartFilename(AaxDecrypter.MultiConvertFileProperties props)
=> MultipartFilename(props, Configuration.Instance.ChapterFileTemplate, AudibleFileStorage.DecryptInProgressDirectory); => Templates.ChapterFile.GetFilename(libraryBook.ToDto(), props);
public string MultipartFilename(AaxDecrypter.MultiConvertFileProperties props, string template, string fullDirPath)
{
var fileNamingTemplate = GetFileNamingTemplate(template, libraryBookDto, fullDirPath, Path.GetExtension(props.OutputFileName));
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChCount, props.PartsTotal);
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChNumber, props.PartsPosition);
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChNumber0, FileUtility.GetSequenceFormatted(props.PartsPosition, props.PartsTotal));
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChTitle, props.Title ?? "");
return fileNamingTemplate.GetFilePath();
}
} }
public static Func<AaxDecrypter.MultiConvertFileProperties, string> CreateMultipartRenamerFunc(this AudioFileStorage _, LibraryBook libraryBook) public static Func<AaxDecrypter.MultiConvertFileProperties, string> CreateMultipartRenamerFunc(this AudioFileStorage _, LibraryBook libraryBook)
=> new MultipartRenamer(libraryBook).MultipartFilename; => new MultipartRenamer(libraryBook).MultipartFilename;
public static Func<AaxDecrypter.MultiConvertFileProperties, string> CreateMultipartRenamerFunc(this AudioFileStorage _, LibraryBookDto libraryBookDto)
=> new MultipartRenamer(libraryBookDto).MultipartFilename;
/// <summary>
/// DownloadDecryptBook:
/// Path: in progress directory.
/// File name: final file name.
/// </summary>
public static string GetInProgressFilename(this AudioFileStorage _, LibraryBook libraryBook, string extension)
=> GetFileNamingTemplate(Configuration.Instance.FileTemplate, libraryBook.ToDto(), AudibleFileStorage.DecryptInProgressDirectory, extension)
.GetFilePath();
/// <summary> /// <summary>
/// DownloadDecryptBook: /// DownloadDecryptBook:
@ -55,50 +31,26 @@ namespace FileLiberator
/// File name: n/a /// File name: n/a
/// </summary> /// </summary>
public static string GetDestinationDirectory(this AudioFileStorage _, LibraryBook libraryBook) public static string GetDestinationDirectory(this AudioFileStorage _, LibraryBook libraryBook)
=> GetFileNamingTemplate(Configuration.Instance.FolderTemplate, libraryBook.ToDto(), AudibleFileStorage.BooksDirectory, null) => Templates.Folder.GetFilename(libraryBook.ToDto());
.GetFilePath();
/// <summary>
/// DownloadDecryptBook:
/// Path: in progress directory.
/// File name: final file name.
/// </summary>
public static string GetInProgressFilename(this AudioFileStorage _, LibraryBook libraryBook, string extension)
=> Templates.File.GetFilename(libraryBook.ToDto(), AudibleFileStorage.DecryptInProgressDirectory, extension);
/// <summary> /// <summary>
/// PDF: audio file does not exist /// PDF: audio file does not exist
/// </summary> /// </summary>
public static string GetBooksDirectoryFilename(this AudioFileStorage _, LibraryBook libraryBook, string extension) public static string GetBooksDirectoryFilename(this AudioFileStorage _, LibraryBook libraryBook, string extension)
=> GetFileNamingTemplate(Configuration.Instance.FileTemplate, libraryBook.ToDto(), AudibleFileStorage.BooksDirectory, extension) => Templates.File.GetFilename(libraryBook.ToDto(), AudibleFileStorage.BooksDirectory, extension);
.GetFilePath();
/// <summary> /// <summary>
/// PDF: audio file already exists /// PDF: audio file already exists
/// </summary> /// </summary>
public static string GetCustomDirFilename(this AudioFileStorage _, LibraryBook libraryBook, string dirFullPath, string extension) public static string GetCustomDirFilename(this AudioFileStorage _, LibraryBook libraryBook, string dirFullPath, string extension)
=> GetFileNamingTemplate(Configuration.Instance.FileTemplate, libraryBook.ToDto(), dirFullPath, extension) => Templates.File.GetFilename(libraryBook.ToDto(), dirFullPath, extension);
.GetFilePath();
public static FileNamingTemplate GetFileNamingTemplate(string template, LibraryBookDto libraryBookDto, string dirFullPath, string extension)
{
ArgumentValidator.EnsureNotNullOrWhiteSpace(template, nameof(template));
ArgumentValidator.EnsureNotNull(libraryBookDto, nameof(libraryBookDto));
dirFullPath = dirFullPath?.Trim() ?? "";
var t = template + FileUtility.GetStandardizedExtension(extension);
var fullfilename = dirFullPath == "" ? t : Path.Combine(dirFullPath, t);
var fileNamingTemplate = new FileNamingTemplate(fullfilename) { IllegalCharacterReplacements = "_" };
var title = libraryBookDto.Title ?? "";
var titleShort = title.IndexOf(':') < 1 ? title : title.Substring(0, title.IndexOf(':'));
fileNamingTemplate.AddParameterReplacement(TemplateTags.Id, libraryBookDto.AudibleProductId);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Title, title);
fileNamingTemplate.AddParameterReplacement(TemplateTags.TitleShort, titleShort);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Author, libraryBookDto.AuthorNames);
fileNamingTemplate.AddParameterReplacement(TemplateTags.FirstAuthor, libraryBookDto.FirstAuthor);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Narrator, libraryBookDto.NarratorNames);
fileNamingTemplate.AddParameterReplacement(TemplateTags.FirstNarrator, libraryBookDto.FirstNarrator);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Series, libraryBookDto.SeriesName);
fileNamingTemplate.AddParameterReplacement(TemplateTags.SeriesNumber, libraryBookDto.SeriesNumber);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Account, libraryBookDto.Account);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Locale, libraryBookDto.Locale);
return fileNamingTemplate;
}
} }
} }

View File

@ -9,6 +9,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\AaxDecrypter\AaxDecrypter.csproj" />
<ProjectReference Include="..\FileManager\FileManager.csproj" /> <ProjectReference Include="..\FileManager\FileManager.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -18,7 +18,7 @@ namespace LibationFileManager
IsChapterOnly = isChapterOnly; IsChapterOnly = isChapterOnly;
} }
// putting these first is the incredibly lazy way to make them show up first in the settings dialog // putting these first is the incredibly lazy way to make them show up first in the EditTemplateDialog
public static TemplateTags ChCount { get; } = new TemplateTags("ch count", "Number of chapters", true); public static TemplateTags ChCount { get; } = new TemplateTags("ch count", "Number of chapters", true);
public static TemplateTags ChTitle { get; } = new TemplateTags("ch title", "Chapter title", true); public static TemplateTags ChTitle { get; } = new TemplateTags("ch title", "Chapter title", true);
public static TemplateTags ChNumber { get; } = new TemplateTags("ch#", "Chapter number", true); public static TemplateTags ChNumber { get; } = new TemplateTags("ch#", "Chapter number", true);

View File

@ -1,4 +1,6 @@
using System; using Dinah.Core;
using FileManager;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -18,74 +20,30 @@ namespace LibationFileManager
public const string WARNING_HAS_CHAPTER_TAGS = "Chapter tags should only be used in the template used for naming files which are split by chapter. Eg: <ch title>"; public const string WARNING_HAS_CHAPTER_TAGS = "Chapter tags should only be used in the template used for naming files which are split by chapter. Eg: <ch title>";
public const string WARNING_NO_CHAPTER_NUMBER_TAG = "Should include chapter number tag in template used for naming files which are split by chapter. Ie: <ch#> or <ch# 0>"; public const string WARNING_NO_CHAPTER_NUMBER_TAG = "Should include chapter number tag in template used for naming files which are split by chapter. Ie: <ch#> or <ch# 0>";
public static Templates Folder { get; } = new FolderTemplate(); public static FolderTemplate Folder { get; } = new FolderTemplate();
public static Templates File { get; } = new FileTemplate(); public static FileTemplate File { get; } = new FileTemplate();
public static Templates ChapterFile { get; } = new ChapterFileTemplate(); public static ChapterFileTemplate ChapterFile { get; } = new ChapterFileTemplate();
public abstract string Name { get; } public abstract string Name { get; }
public abstract string Description { get; } public abstract string Description { get; }
public abstract string DefaultTemplate { get; } public abstract string DefaultTemplate { get; }
protected abstract bool IsChapterized { get; } protected abstract bool IsChapterized { get; }
internal string GetValid(string configValue) protected Templates() { }
#region validation
internal string GetValid(string configValue)
{ {
var value = configValue?.Trim(); var value = configValue?.Trim();
return IsValid(value) ? value : DefaultTemplate; return IsValid(value) ? value : DefaultTemplate;
} }
public static string Sanitize(string template)
{
var value = template ?? "";
// don't use alt slash
value = value.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
// don't allow double slashes
var sing = $"{Path.DirectorySeparatorChar}";
var dbl = $"{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}";
while (value.Contains(dbl))
value = value.Replace(dbl, sing);
// trim. don't start or end with slash
while (true)
{
var start = value.Length;
value = value
.Trim()
.Trim(Path.DirectorySeparatorChar);
var end = value.Length;
if (start == end)
break;
}
return value;
}
public abstract IEnumerable<string> GetErrors(string template); public abstract IEnumerable<string> GetErrors(string template);
public bool IsValid(string template) => !GetErrors(template).Any(); public bool IsValid(string template) => !GetErrors(template).Any();
public abstract IEnumerable<string> GetWarnings(string template); public abstract IEnumerable<string> GetWarnings(string template);
public bool HasWarnings(string template) => GetWarnings(template).Any(); public bool HasWarnings(string template) => GetWarnings(template).Any();
public IEnumerable<TemplateTags> GetTemplateTags()
=> TemplateTags.GetAll()
// yeah, this line is a little funky but it works when you think through it. also: trust the unit tests
.Where(t => IsChapterized || !t.IsChapterOnly);
public int TagCount(string template)
=> GetTemplateTags()
// for <id><id> == 1, use:
// .Count(t => template.Contains($"<{t.TagName}>"))
// .Sum() impl: <id><id> == 2
.Sum(t => template.Split($"<{t.TagName}>").Length - 1);
public static bool ContainsChapterOnlyTags(string template)
=> TemplateTags.GetAll()
.Where(t => t.IsChapterOnly)
.Any(t => ContainsTag(template, t.TagName));
public static bool ContainsTag(string template, string tag) => template.Contains($"<{tag}>");
protected static string[] GetFileErrors(string template) protected static string[] GetFileErrors(string template)
{ {
// File name only; not path. all other path chars are valid enough to pass this check and will be handled on final save. // File name only; not path. all other path chars are valid enough to pass this check and will be handled on final save.
@ -123,13 +81,102 @@ namespace LibationFileManager
return warnings; return warnings;
} }
private class FolderTemplate : Templates internal int TagCount(string template)
=> GetTemplateTags()
// for <id><id> == 1, use:
// .Count(t => template.Contains($"<{t.TagName}>"))
// .Sum() impl: <id><id> == 2
.Sum(t => template.Split($"<{t.TagName}>").Length - 1);
internal static bool ContainsChapterOnlyTags(string template)
=> TemplateTags.GetAll()
.Where(t => t.IsChapterOnly)
.Any(t => ContainsTag(template, t.TagName));
internal static bool ContainsTag(string template, string tag) => template.Contains($"<{tag}>");
#endregion
#region to file name
/// <summary>
/// EditTemplateDialog: Get template generated filename for portion of path
/// </summary>
public string GetPortionFilename(LibraryBookDto libraryBookDto, string template)
=> getFileNamingTemplate(libraryBookDto, template, null, null)
.GetFilePath();
internal static FileNamingTemplate getFileNamingTemplate(LibraryBookDto libraryBookDto, string template, string dirFullPath, string extension)
{
ArgumentValidator.EnsureNotNullOrWhiteSpace(template, nameof(template));
ArgumentValidator.EnsureNotNull(libraryBookDto, nameof(libraryBookDto));
dirFullPath = dirFullPath?.Trim() ?? "";
var t = template + FileUtility.GetStandardizedExtension(extension);
var fullfilename = dirFullPath == "" ? t : Path.Combine(dirFullPath, t);
var fileNamingTemplate = new FileNamingTemplate(fullfilename) { IllegalCharacterReplacements = "_" };
var title = libraryBookDto.Title ?? "";
var titleShort = title.IndexOf(':') < 1 ? title : title.Substring(0, title.IndexOf(':'));
fileNamingTemplate.AddParameterReplacement(TemplateTags.Id, libraryBookDto.AudibleProductId);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Title, title);
fileNamingTemplate.AddParameterReplacement(TemplateTags.TitleShort, titleShort);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Author, libraryBookDto.AuthorNames);
fileNamingTemplate.AddParameterReplacement(TemplateTags.FirstAuthor, libraryBookDto.FirstAuthor);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Narrator, libraryBookDto.NarratorNames);
fileNamingTemplate.AddParameterReplacement(TemplateTags.FirstNarrator, libraryBookDto.FirstNarrator);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Series, libraryBookDto.SeriesName);
fileNamingTemplate.AddParameterReplacement(TemplateTags.SeriesNumber, libraryBookDto.SeriesNumber);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Account, libraryBookDto.Account);
fileNamingTemplate.AddParameterReplacement(TemplateTags.Locale, libraryBookDto.Locale);
return fileNamingTemplate;
}
#endregion
public IEnumerable<TemplateTags> GetTemplateTags()
=> TemplateTags.GetAll()
// yeah, this line is a little funky but it works when you think through it. also: trust the unit tests
.Where(t => IsChapterized || !t.IsChapterOnly);
public string Sanitize(string template)
{
var value = template ?? "";
// don't use alt slash
value = value.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
// don't allow double slashes
var sing = $"{Path.DirectorySeparatorChar}";
var dbl = $"{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}";
while (value.Contains(dbl))
value = value.Replace(dbl, sing);
// trim. don't start or end with slash
while (true)
{
var start = value.Length;
value = value
.Trim()
.Trim(Path.DirectorySeparatorChar);
var end = value.Length;
if (start == end)
break;
}
return value;
}
public class FolderTemplate : Templates
{ {
public override string Name => "Folder Template"; public override string Name => "Folder Template";
public override string Description => Configuration.GetDescription(nameof(Configuration.FolderTemplate)); public override string Description => Configuration.GetDescription(nameof(Configuration.FolderTemplate));
public override string DefaultTemplate { get; } = "<title short> [<id>]"; public override string DefaultTemplate { get; } = "<title short> [<id>]";
protected override bool IsChapterized { get; } = false; protected override bool IsChapterized { get; } = false;
internal FolderTemplate() : base() { }
#region validation
public override IEnumerable<string> GetErrors(string template) public override IEnumerable<string> GetErrors(string template)
{ {
// null is invalid. whitespace is valid but not recommended // null is invalid. whitespace is valid but not recommended
@ -144,27 +191,49 @@ namespace LibationFileManager
} }
public override IEnumerable<string> GetWarnings(string template) => GetStandardWarnings(template); public override IEnumerable<string> GetWarnings(string template) => GetStandardWarnings(template);
#endregion
#region to file name
/// <summary>USES LIVE CONFIGURATION VALUES</summary>
public string GetFilename(LibraryBookDto libraryBookDto)
=> getFileNamingTemplate(libraryBookDto, Configuration.Instance.FolderTemplate, AudibleFileStorage.BooksDirectory, null)
.GetFilePath();
#endregion
} }
private class FileTemplate : Templates public class FileTemplate : Templates
{ {
public override string Name => "File Template"; public override string Name => "File Template";
public override string Description => Configuration.GetDescription(nameof(Configuration.FileTemplate)); public override string Description => Configuration.GetDescription(nameof(Configuration.FileTemplate));
public override string DefaultTemplate { get; } = "<title> [<id>]"; public override string DefaultTemplate { get; } = "<title> [<id>]";
protected override bool IsChapterized { get; } = false; protected override bool IsChapterized { get; } = false;
internal FileTemplate() : base() { }
#region validation
public override IEnumerable<string> GetErrors(string template) => GetFileErrors(template); public override IEnumerable<string> GetErrors(string template) => GetFileErrors(template);
public override IEnumerable<string> GetWarnings(string template) => GetStandardWarnings(template); public override IEnumerable<string> GetWarnings(string template) => GetStandardWarnings(template);
#endregion
#region to file name
/// <summary>USES LIVE CONFIGURATION VALUES</summary>
public string GetFilename(LibraryBookDto libraryBookDto, string dirFullPath, string extension)
=> getFileNamingTemplate(libraryBookDto, Configuration.Instance.FileTemplate, dirFullPath, extension)
.GetFilePath();
#endregion
} }
private class ChapterFileTemplate : Templates public class ChapterFileTemplate : Templates
{ {
public override string Name => "Chapter File Template"; public override string Name => "Chapter File Template";
public override string Description => Configuration.GetDescription(nameof(Configuration.ChapterFileTemplate)); public override string Description => Configuration.GetDescription(nameof(Configuration.ChapterFileTemplate));
public override string DefaultTemplate { get; } = "<title> [<id>] - <ch# 0> - <ch title>"; public override string DefaultTemplate { get; } = "<title> [<id>] - <ch# 0> - <ch title>";
protected override bool IsChapterized { get; } = true; protected override bool IsChapterized { get; } = true;
internal ChapterFileTemplate() : base() { }
#region validation
public override IEnumerable<string> GetErrors(string template) => GetFileErrors(template); public override IEnumerable<string> GetErrors(string template) => GetFileErrors(template);
public override IEnumerable<string> GetWarnings(string template) public override IEnumerable<string> GetWarnings(string template)
@ -178,7 +247,26 @@ namespace LibationFileManager
warnings.Add(WARNING_NO_CHAPTER_NUMBER_TAG); warnings.Add(WARNING_NO_CHAPTER_NUMBER_TAG);
return warnings; return warnings;
} }
#endregion
#region to file name
/// <summary>USES LIVE CONFIGURATION VALUES</summary>
public string GetFilename(LibraryBookDto libraryBookDto, AaxDecrypter.MultiConvertFileProperties props)
=> GetPortionFilename(libraryBookDto, Configuration.Instance.ChapterFileTemplate, props, AudibleFileStorage.DecryptInProgressDirectory);
public string GetPortionFilename(LibraryBookDto libraryBookDto, string template, AaxDecrypter.MultiConvertFileProperties props, string fullDirPath)
{
var fileNamingTemplate = getFileNamingTemplate(libraryBookDto, template, fullDirPath, Path.GetExtension(props.OutputFileName));
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChCount, props.PartsTotal);
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChNumber, props.PartsPosition);
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChNumber0, FileUtility.GetSequenceFormatted(props.PartsPosition, props.PartsTotal));
fileNamingTemplate.AddParameterReplacement(TemplateTags.ChTitle, props.Title ?? "");
return fileNamingTemplate.GetFilePath();
}
#endregion
} }
} }
} }

View File

@ -10,15 +10,15 @@ namespace LibationWinForms.Dialogs
{ {
public partial class EditTemplateDialog : Form public partial class EditTemplateDialog : Form
{ {
// final valid value // final value. post-validity check
public string TemplateText { get; private set; } public string TemplateText { get; private set; }
// work-in-progress. not guaranteed to be valid // hold the work-in-progress value. not guaranteed to be valid
private string _workingTemplateText; private string _workingTemplateText;
private string workingTemplateText private string workingTemplateText
{ {
get => _workingTemplateText; get => _workingTemplateText;
set => _workingTemplateText = Templates.Sanitize(value); set => _workingTemplateText = template.Sanitize(value);
} }
private void resetTextBox(string value) => this.templateTb.Text = workingTemplateText = value; private void resetTextBox(string value) => this.templateTb.Text = workingTemplateText = value;
@ -82,24 +82,19 @@ namespace LibationWinForms.Dialogs
var chaptersTotal = 10; var chaptersTotal = 10;
var books = config.Books; var books = config.Books;
var folder = FileLiberator.AudioFileStorageExt.GetFileNamingTemplate( var folder = Templates.Folder.GetPortionFilename(
isFolder ? workingTemplateText : config.FolderTemplate,
libraryBookDto, libraryBookDto,
null, isFolder ? workingTemplateText : config.FolderTemplate);
null)
.GetFilePath();
var file var file
= (template == Templates.ChapterFile) = template == Templates.ChapterFile
? new FileLiberator.AudioFileStorageExt.MultipartRenamer(libraryBookDto).MultipartFilename( ? Templates.ChapterFile.GetPortionFilename(
new() { OutputFileName = "", PartsPosition = chapterNumber, PartsTotal = chaptersTotal, Title = chapterName },
workingTemplateText,
"")
: FileLiberator.AudioFileStorageExt.GetFileNamingTemplate(
isFolder ? config.FileTemplate : workingTemplateText,
libraryBookDto, libraryBookDto,
null, workingTemplateText,
null) new() { OutputFileName = "", PartsPosition = chapterNumber, PartsTotal = chaptersTotal, Title = chapterName },
.GetFilePath(); "")
: Templates.File.GetPortionFilename(
libraryBookDto,
isFolder ? config.FileTemplate : workingTemplateText);
var ext = config.DecryptToLossy ? "mp3" : "m4b"; var ext = config.DecryptToLossy ? "mp3" : "m4b";
const char ZERO_WIDTH_SPACE = '\u200B'; const char ZERO_WIDTH_SPACE = '\u200B';

View File

@ -108,19 +108,11 @@ namespace LibationWinForms.Dialogs
private void chapterFileTemplateBtn_Click(object sender, EventArgs e) => editTemplate(Templates.ChapterFile, chapterFileTemplateTb); private void chapterFileTemplateBtn_Click(object sender, EventArgs e) => editTemplate(Templates.ChapterFile, chapterFileTemplateTb);
private static void editTemplate(Templates template, TextBox textBox) private static void editTemplate(Templates template, TextBox textBox)
{ {
#if !DEBUG
TEMP_TEMP_TEMP();
return;
#endif
var form = new EditTemplateDialog(template, textBox.Text); var form = new EditTemplateDialog(template, textBox.Text);
if (form.ShowDialog() == DialogResult.OK) if (form.ShowDialog() == DialogResult.OK)
textBox.Text = form.TemplateText; textBox.Text = form.TemplateText;
} }
private static void TEMP_TEMP_TEMP()
=> MessageBox.Show("Sorry, not yet. Coming soon :)");
private void saveBtn_Click(object sender, EventArgs e) private void saveBtn_Click(object sender, EventArgs e)
{ {
var newBooks = booksSelectControl.SelectedDirectory; var newBooks = booksSelectControl.SelectedDirectory;

View File

@ -1,69 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dinah.Core;
using FileLiberator;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using static AudioFileStorageExtTests.Shared;
namespace AudioFileStorageExtTests
{
public static class Shared
{
public static LibationFileManager.LibraryBookDto GetLibraryBook(string asin)
=> new()
{
Account = "my account",
AudibleProductId = asin,
Title = "A Study in Scarlet: A Sherlock Holmes Novel",
Locale = "us",
Authors = new List<string> { "Arthur Conan Doyle", "Stephen Fry - introductions" },
Narrators = new List<string> { "Stephen Fry" },
SeriesName = "Sherlock Holmes",
SeriesNumber = "1"
};
}
[TestClass]
public class MultipartRenamer_MultipartFilename
{
[TestMethod]
[DataRow("asin", "[<id>] <ch# 0> of <ch count> - <ch title>", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\[asin] 06 of 10 - chap.txt")]
[DataRow("asin", "<ch#>", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\6.txt")]
public void Tests(string asin, string template, string dir, string ext, int pos, int total, string chapter, string expected)
=> new AudioFileStorageExt.MultipartRenamer(GetLibraryBook(asin))
.MultipartFilename(new() { OutputFileName = $"xyz.{ext}", PartsPosition = pos, PartsTotal = total, Title = chapter }, template, dir)
.Should().Be(expected);
}
[TestClass]
public class GetFileNamingTemplate
{
[TestMethod]
[DataRow(null, "asin", @"C:\", "ext")]
[ExpectedException(typeof(ArgumentNullException))]
public void arg_null_exception(string template, string asin, string dirFullPath, string extension)
=> AudioFileStorageExt.GetFileNamingTemplate(template, GetLibraryBook(asin), dirFullPath, extension);
[TestMethod]
[DataRow("", "asin", @"C:\foo\bar", "ext")]
[DataRow(" ", "asin", @"C:\foo\bar", "ext")]
[ExpectedException(typeof(ArgumentException))]
public void arg_exception(string template, string asin, string dirFullPath, string extension)
=> AudioFileStorageExt.GetFileNamingTemplate(template, GetLibraryBook(asin), dirFullPath, extension);
[TestMethod]
public void null_extension() => Tests("f.txt", "asin", @"C:\foo\bar", null, @"C:\foo\bar\f.txt");
[TestMethod]
[DataRow("f.txt", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\f.txt.ext")]
[DataRow("f", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\f.ext")]
[DataRow("<id>", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\asin.ext")]
public void Tests(string template, string asin, string dirFullPath, string extension, string expected)
=> AudioFileStorageExt.GetFileNamingTemplate(template, GetLibraryBook(asin), dirFullPath, extension)
.GetFilePath()
.Should().Be(expected);
}
}

View File

@ -7,8 +7,26 @@ using FluentAssertions;
using LibationFileManager; using LibationFileManager;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using static TemplatesTests.Shared;
namespace TemplatesTests namespace TemplatesTests
{ {
public static class Shared
{
public static LibraryBookDto GetLibraryBook(string asin)
=> new()
{
Account = "my account",
AudibleProductId = asin,
Title = "A Study in Scarlet: A Sherlock Holmes Novel",
Locale = "us",
Authors = new List<string> { "Arthur Conan Doyle", "Stephen Fry - introductions" },
Narrators = new List<string> { "Stephen Fry" },
SeriesName = "Sherlock Holmes",
SeriesNumber = "1"
};
}
[TestClass] [TestClass]
public class ContainsChapterOnlyTags public class ContainsChapterOnlyTags
{ {
@ -29,6 +47,35 @@ namespace TemplatesTests
[DataRow("<id><ch#>", "ch#", true)] [DataRow("<id><ch#>", "ch#", true)]
public void Tests(string template, string tag, bool expected) => Templates.ContainsTag(template, tag).Should().Be(expected); public void Tests(string template, string tag, bool expected) => Templates.ContainsTag(template, tag).Should().Be(expected);
} }
[TestClass]
public class getFileNamingTemplate
{
[TestMethod]
[DataRow(null, "asin", @"C:\", "ext")]
[ExpectedException(typeof(ArgumentNullException))]
public void arg_null_exception(string template, string asin, string dirFullPath, string extension)
=> Templates.getFileNamingTemplate(GetLibraryBook(asin), template, dirFullPath, extension);
[TestMethod]
[DataRow("", "asin", @"C:\foo\bar", "ext")]
[DataRow(" ", "asin", @"C:\foo\bar", "ext")]
[ExpectedException(typeof(ArgumentException))]
public void arg_exception(string template, string asin, string dirFullPath, string extension)
=> Templates.getFileNamingTemplate(GetLibraryBook(asin), template, dirFullPath, extension);
[TestMethod]
public void null_extension() => Tests("f.txt", "asin", @"C:\foo\bar", null, @"C:\foo\bar\f.txt");
[TestMethod]
[DataRow("f.txt", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\f.txt.ext")]
[DataRow("f", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\f.ext")]
[DataRow("<id>", "asin", @"C:\foo\bar", "ext", @"C:\foo\bar\asin.ext")]
public void Tests(string template, string asin, string dirFullPath, string extension, string expected)
=> Templates.getFileNamingTemplate(GetLibraryBook(asin), template, dirFullPath, extension)
.GetFilePath()
.Should().Be(expected);
}
} }
namespace Templates_Folder_Tests namespace Templates_Folder_Tests
@ -314,4 +361,15 @@ namespace Templates_ChapterFile_Tests
[DataRow("<ID> case specific", 0)] [DataRow("<ID> case specific", 0)]
public void Tests(string template, int expected) => Templates.ChapterFile.TagCount(template).Should().Be(expected); public void Tests(string template, int expected) => Templates.ChapterFile.TagCount(template).Should().Be(expected);
} }
[TestClass]
public class GetPortionFilename
{
[TestMethod]
[DataRow("asin", "[<id>] <ch# 0> of <ch count> - <ch title>", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\[asin] 06 of 10 - chap.txt")]
[DataRow("asin", "<ch#>", @"C:\foo\", "txt", 6, 10, "chap", @"C:\foo\6.txt")]
public void Tests(string asin, string template, string dir, string ext, int pos, int total, string chapter, string expected)
=> Templates.ChapterFile.GetPortionFilename(GetLibraryBook(asin), template, new() { OutputFileName = $"xyz.{ext}", PartsPosition = pos, PartsTotal = total, Title = chapter }, dir)
.Should().Be(expected);
}
} }