Naming logic for all new files can now originate from domian logic
This commit is contained in:
parent
87e3075fb3
commit
e4fc104afe
@ -12,10 +12,23 @@ namespace AaxDecrypter
|
|||||||
{
|
{
|
||||||
protected override StepSequence Steps { get; }
|
protected override StepSequence Steps { get; }
|
||||||
|
|
||||||
private static TimeSpan minChapterLength { get; } = TimeSpan.FromSeconds(3);
|
private Func<string, int, int, NewSplitCallback, string> multipartFileNameCallback { get; }
|
||||||
|
private static string DefaultMultipartFileName(string outputFileName, int partsPosition, int partsTotal, NewSplitCallback newSplitCallback)
|
||||||
|
{
|
||||||
|
var template = Path.ChangeExtension(outputFileName, null) + " - <chapter> - <title>" + Path.GetExtension(outputFileName);
|
||||||
|
|
||||||
|
var fileTemplate = new FileTemplate(template) { IllegalCharacterReplacements = " " };
|
||||||
|
fileTemplate.AddParameterReplacement("chapter", FileUtility.GetSequenceFormatted(partsPosition, partsTotal));
|
||||||
|
fileTemplate.AddParameterReplacement("title", newSplitCallback?.Chapter?.Title ?? "");
|
||||||
|
|
||||||
|
return fileTemplate.GetFilename();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TimeSpan minChapterLength { get; } = TimeSpan.FromSeconds(3);
|
||||||
private List<string> multiPartFilePaths { get; } = new List<string>();
|
private List<string> multiPartFilePaths { get; } = new List<string>();
|
||||||
|
|
||||||
public AaxcDownloadMultiConverter(string outFileName, string cacheDirectory, DownloadLicense dlLic, OutputFormat outputFormat)
|
public AaxcDownloadMultiConverter(string outFileName, string cacheDirectory, DownloadLicense dlLic, OutputFormat outputFormat,
|
||||||
|
Func<string, int, int, NewSplitCallback, string> multipartFileNameCallback = null)
|
||||||
: base(outFileName, cacheDirectory, dlLic, outputFormat)
|
: base(outFileName, cacheDirectory, dlLic, outputFormat)
|
||||||
{
|
{
|
||||||
Steps = new StepSequence
|
Steps = new StepSequence
|
||||||
@ -26,6 +39,7 @@ namespace AaxDecrypter
|
|||||||
["Step 2: Download Decrypted Audiobook"] = Step_DownloadAudiobookAsMultipleFilesPerChapter,
|
["Step 2: Download Decrypted Audiobook"] = Step_DownloadAudiobookAsMultipleFilesPerChapter,
|
||||||
["Step 3: Cleanup"] = Step_Cleanup,
|
["Step 3: Cleanup"] = Step_Cleanup,
|
||||||
};
|
};
|
||||||
|
this.multipartFileNameCallback = multipartFileNameCallback ?? DefaultMultipartFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -119,7 +133,9 @@ That naming may not be desirable for everyone, but it's an easy change to instea
|
|||||||
|
|
||||||
private void createOutputFileStream(int currentChapter, ChapterInfo splitChapters, NewSplitCallback newSplitCallback)
|
private void createOutputFileStream(int currentChapter, ChapterInfo splitChapters, NewSplitCallback newSplitCallback)
|
||||||
{
|
{
|
||||||
var fileName = FileUtility.GetMultipartFileName(OutputFileName, currentChapter, splitChapters.Count, newSplitCallback.Chapter.Title);
|
var fileName = multipartFileNameCallback(OutputFileName, currentChapter, splitChapters.Count, newSplitCallback);
|
||||||
|
fileName = FileUtility.GetValidFilename(fileName);
|
||||||
|
|
||||||
multiPartFilePaths.Add(fileName);
|
multiPartFilePaths.Add(fileName);
|
||||||
|
|
||||||
FileUtility.SaferDelete(fileName);
|
FileUtility.SaferDelete(fileName);
|
||||||
|
|||||||
@ -46,9 +46,10 @@ namespace AaxDecrypter
|
|||||||
throw new DirectoryNotFoundException($"Directory does not exist: {nameof(cacheDirectory)}");
|
throw new DirectoryNotFoundException($"Directory does not exist: {nameof(cacheDirectory)}");
|
||||||
cacheDir = cacheDirectory;
|
cacheDir = cacheDirectory;
|
||||||
|
|
||||||
|
DownloadLicense = ArgumentValidator.EnsureNotNull(dlLic, nameof(dlLic));
|
||||||
|
|
||||||
// delete file after validation is complete
|
// delete file after validation is complete
|
||||||
FileUtility.SaferDelete(OutputFileName);
|
FileUtility.SaferDelete(OutputFileName);
|
||||||
DownloadLicense = ArgumentValidator.EnsureNotNull(dlLic, nameof(dlLic));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void Cancel();
|
public abstract void Cancel();
|
||||||
|
|||||||
@ -86,45 +86,39 @@ namespace FileUtilityTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class GetMultipartFileName
|
public class GetSequenceFormatted
|
||||||
{
|
{
|
||||||
[TestMethod]
|
|
||||||
public void null_path() => Assert.ThrowsException<ArgumentNullException>(() => FileUtility.GetMultipartFileName(null, 1, 1, ""));
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public void null_suffix() => Tests(@"C:\foo\bar\my file.txt", 2, 100, null, @"C:\foo\bar\my file - 002 - .txt");
|
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void negative_partsPosition() => Assert.ThrowsException<ArgumentException>(()
|
public void negative_partsPosition() => Assert.ThrowsException<ArgumentException>(()
|
||||||
=> FileUtility.GetMultipartFileName("foo", -1, 2, "")
|
=> FileUtility.GetSequenceFormatted(-1, 2)
|
||||||
);
|
);
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void zero_partsPosition() => Assert.ThrowsException<ArgumentException>(()
|
public void zero_partsPosition() => Assert.ThrowsException<ArgumentException>(()
|
||||||
=> FileUtility.GetMultipartFileName("foo", 0, 2, "")
|
=> FileUtility.GetSequenceFormatted(0, 2)
|
||||||
);
|
);
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void negative_partsTotal() => Assert.ThrowsException<ArgumentException>(()
|
public void negative_partsTotal() => Assert.ThrowsException<ArgumentException>(()
|
||||||
=> FileUtility.GetMultipartFileName("foo", 2, -1, "")
|
=> FileUtility.GetSequenceFormatted(2, -1)
|
||||||
);
|
);
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void zero_partsTotal() => Assert.ThrowsException<ArgumentException>(()
|
public void zero_partsTotal() => Assert.ThrowsException<ArgumentException>(()
|
||||||
=> FileUtility.GetMultipartFileName("foo", 2, 0, "")
|
=> FileUtility.GetSequenceFormatted(2, 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void partsPosition_greater_than_partsTotal() => Assert.ThrowsException<ArgumentException>(()
|
public void partsPosition_greater_than_partsTotal() => Assert.ThrowsException<ArgumentException>(()
|
||||||
=> FileUtility.GetMultipartFileName("foo", 2, 1, "")
|
=> FileUtility.GetSequenceFormatted(2, 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
// only part
|
// only part
|
||||||
[DataRow(@"C:\foo\bar\my file.txt", 1, 1, "title", @"C:\foo\bar\my file - 1 - title.txt")]
|
[DataRow(1, 1, "1")]
|
||||||
|
// 2 digits
|
||||||
|
[DataRow(2, 90, "02")]
|
||||||
// 3 digits
|
// 3 digits
|
||||||
[DataRow(@"C:\foo\bar\my file.txt", 2, 100, "title", @"C:\foo\bar\my file - 002 - title.txt")]
|
[DataRow(2, 900, "002")]
|
||||||
// no suffix
|
public void Tests(int partsPosition, int partsTotal, string expected)
|
||||||
[DataRow(@"C:\foo\bar\my file.txt", 2, 100, "", @"C:\foo\bar\my file - 002 - .txt")]
|
=> FileUtility.GetSequenceFormatted(partsPosition, partsTotal).Should().Be(expected);
|
||||||
public void Tests(string originalPath, int partsPosition, int partsTotal, string suffix, string expected)
|
|
||||||
=> FileUtility.GetMultipartFileName(originalPath, partsPosition, partsTotal, suffix).Should().Be(expected);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,26 +35,22 @@ namespace FileManager
|
|||||||
return fileTemplate.GetFilename();
|
return fileTemplate.GetFilename();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetMultipartFileName(string originalPath, int partsPosition, int partsTotal, string suffix)
|
/// <summary>
|
||||||
|
/// Return position with correct number of leading zeros.
|
||||||
|
/// <br />- 2 of 9 => "2"
|
||||||
|
/// <br />- 2 of 90 => "02"
|
||||||
|
/// <br />- 2 of 900 => "002"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">position in sequence. The 'x' in 'x of y'</param>
|
||||||
|
/// <param name="total">total qty in sequence. The 'y' in 'x of y'</param>
|
||||||
|
public static string GetSequenceFormatted(int position, int total)
|
||||||
{
|
{
|
||||||
ArgumentValidator.EnsureNotNull(originalPath, nameof(originalPath));
|
ArgumentValidator.EnsureGreaterThan(position, nameof(position), 0);
|
||||||
ArgumentValidator.EnsureGreaterThan(partsPosition, nameof(partsPosition), 0);
|
ArgumentValidator.EnsureGreaterThan(total, nameof(total), 0);
|
||||||
ArgumentValidator.EnsureGreaterThan(partsTotal, nameof(partsTotal), 0);
|
if (position > total)
|
||||||
if (partsPosition > partsTotal)
|
throw new ArgumentException($"{position} may not be greater than {total}");
|
||||||
throw new ArgumentException($"{partsPosition} may not be greater than {partsTotal}");
|
|
||||||
|
|
||||||
// 1-9 => 1-9
|
return position.ToString().PadLeft(total.ToString().Length, '0');
|
||||||
// 10-99 => 01-99
|
|
||||||
// 100-999 => 001-999
|
|
||||||
var chapterCountLeadingZeros = partsPosition.ToString().PadLeft(partsTotal.ToString().Length, '0');
|
|
||||||
|
|
||||||
var template = Path.ChangeExtension(originalPath, null) + " - <chapter> - <title>" + Path.GetExtension(originalPath);
|
|
||||||
|
|
||||||
var fileTemplate = new FileTemplate(template) { IllegalCharacterReplacements = " " };
|
|
||||||
fileTemplate.AddParameterReplacement("chapter", chapterCountLeadingZeros);
|
|
||||||
fileTemplate.AddParameterReplacement("title", suffix);
|
|
||||||
|
|
||||||
return fileTemplate.GetFilename();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int MAX_FILENAME_LENGTH = 255;
|
private const int MAX_FILENAME_LENGTH = 255;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user