Convert IProcessable to abstract class Processable.
This commit is contained in:
parent
be5e18d977
commit
6e66314605
11 changed files with 143 additions and 141 deletions
|
|
@ -12,39 +12,32 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace FileLiberator
|
||||
{
|
||||
public class ConvertToMp3 : IAudioDecodable
|
||||
public class ConvertToMp3 : Processable, IAudioDecodable
|
||||
{
|
||||
private Mp4File m4bBook;
|
||||
|
||||
public event EventHandler<TimeSpan> StreamingTimeRemaining;
|
||||
public event EventHandler<Action<byte[]>> RequestCoverArt;
|
||||
public event EventHandler<string> TitleDiscovered;
|
||||
public event EventHandler<string> AuthorsDiscovered;
|
||||
public event EventHandler<string> NarratorsDiscovered;
|
||||
public event EventHandler<byte[]> CoverImageDiscovered;
|
||||
public event EventHandler<string> StreamingBegin;
|
||||
public event EventHandler<DownloadProgress> StreamingProgressChanged;
|
||||
public event EventHandler<string> StreamingCompleted;
|
||||
public event EventHandler<LibraryBook> Begin;
|
||||
public event EventHandler<string> StatusUpdate;
|
||||
public event EventHandler<LibraryBook> Completed;
|
||||
|
||||
private long fileSize;
|
||||
private string Mp3FileName(string m4bPath) => m4bPath is null ? string.Empty : PathLib.ReplaceExtension(m4bPath, ".mp3");
|
||||
|
||||
public void Cancel() => m4bBook?.Cancel();
|
||||
|
||||
public bool Validate(LibraryBook libraryBook)
|
||||
public override bool Validate(LibraryBook libraryBook)
|
||||
{
|
||||
var path = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId);
|
||||
return path?.ToLower()?.EndsWith(".m4b") == true && !File.Exists(Mp3FileName(path));
|
||||
}
|
||||
|
||||
public async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
||||
public override async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
||||
{
|
||||
Begin?.Invoke(this, libraryBook);
|
||||
OnBegin(libraryBook);
|
||||
|
||||
StreamingBegin?.Invoke(this, $"Begin converting {libraryBook} to mp3");
|
||||
OnStreamingBegin($"Begin converting {libraryBook} to mp3");
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -78,8 +71,8 @@ namespace FileLiberator
|
|||
}
|
||||
finally
|
||||
{
|
||||
StreamingCompleted?.Invoke(this, $"Completed converting to mp3: {libraryBook.Book.Title}");
|
||||
Completed?.Invoke(this, libraryBook);
|
||||
OnStreamingCompleted($"Completed converting to mp3: {libraryBook.Book.Title}");
|
||||
OnCompleted(libraryBook);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -90,11 +83,11 @@ namespace FileLiberator
|
|||
double estTimeRemaining = remainingSecsToProcess / e.ProcessSpeed;
|
||||
|
||||
if (double.IsNormal(estTimeRemaining))
|
||||
StreamingTimeRemaining?.Invoke(this, TimeSpan.FromSeconds(estTimeRemaining));
|
||||
OnStreamingTimeRemaining(TimeSpan.FromSeconds(estTimeRemaining));
|
||||
|
||||
double progressPercent = 100 * e.ProcessPosition.TotalSeconds / duration.TotalSeconds;
|
||||
|
||||
StreamingProgressChanged?.Invoke(this,
|
||||
OnStreamingProgressChanged(
|
||||
new DownloadProgress
|
||||
{
|
||||
ProgressPercentage = progressPercent,
|
||||
|
|
|
|||
|
|
@ -13,26 +13,19 @@ using FileManager;
|
|||
|
||||
namespace FileLiberator
|
||||
{
|
||||
public class DownloadDecryptBook : IAudioDecodable
|
||||
public class DownloadDecryptBook : Processable, IAudioDecodable
|
||||
{
|
||||
private AudiobookDownloadBase aaxcDownloader;
|
||||
|
||||
public event EventHandler<TimeSpan> StreamingTimeRemaining;
|
||||
public event EventHandler<Action<byte[]>> RequestCoverArt;
|
||||
public event EventHandler<string> TitleDiscovered;
|
||||
public event EventHandler<string> AuthorsDiscovered;
|
||||
public event EventHandler<string> NarratorsDiscovered;
|
||||
public event EventHandler<byte[]> CoverImageDiscovered;
|
||||
public event EventHandler<string> StreamingBegin;
|
||||
public event EventHandler<DownloadProgress> StreamingProgressChanged;
|
||||
public event EventHandler<string> StreamingCompleted;
|
||||
public event EventHandler<LibraryBook> Begin;
|
||||
public event EventHandler<string> StatusUpdate;
|
||||
public event EventHandler<LibraryBook> Completed;
|
||||
|
||||
public async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
||||
public override async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
||||
{
|
||||
Begin?.Invoke(this, libraryBook);
|
||||
OnBegin(libraryBook);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -57,13 +50,13 @@ namespace FileLiberator
|
|||
}
|
||||
finally
|
||||
{
|
||||
Completed?.Invoke(this, libraryBook);
|
||||
OnCompleted(libraryBook);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> downloadAudiobookAsync(string cacheDir, string destinationDir, LibraryBook libraryBook)
|
||||
{
|
||||
StreamingBegin?.Invoke(this, $"Begin decrypting {libraryBook}");
|
||||
OnStreamingBegin($"Begin decrypting {libraryBook}");
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -101,8 +94,8 @@ namespace FileLiberator
|
|||
aaxcDownloader = contentLic.DrmType == AudibleApi.Common.DrmType.Adrm
|
||||
? new AaxcDownloadConverter(outFileName, cacheDir, audiobookDlLic, outputFormat, Configuration.Instance.SplitFilesByChapter) { AppName = "Libation" }
|
||||
: new UnencryptedAudiobookDownloader(outFileName, cacheDir, audiobookDlLic);
|
||||
aaxcDownloader.DecryptProgressUpdate += (s, progress) => StreamingProgressChanged?.Invoke(this, progress);
|
||||
aaxcDownloader.DecryptTimeRemaining += (s, remaining) => StreamingTimeRemaining?.Invoke(this, remaining);
|
||||
aaxcDownloader.DecryptProgressUpdate += (s, progress) => OnStreamingProgressChanged(progress);
|
||||
aaxcDownloader.DecryptTimeRemaining += (s, remaining) => OnStreamingTimeRemaining(remaining);
|
||||
aaxcDownloader.RetrievedTitle += (s, title) => TitleDiscovered?.Invoke(this, title);
|
||||
aaxcDownloader.RetrievedAuthors += (s, authors) => AuthorsDiscovered?.Invoke(this, authors);
|
||||
aaxcDownloader.RetrievedNarrators += (s, narrators) => NarratorsDiscovered?.Invoke(this, narrators);
|
||||
|
|
@ -119,7 +112,7 @@ namespace FileLiberator
|
|||
}
|
||||
finally
|
||||
{
|
||||
StreamingCompleted?.Invoke(this, $"Completed downloading and decrypting {libraryBook.Book.Title}");
|
||||
OnStreamingCompleted($"Completed downloading and decrypting {libraryBook.Book.Title}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +207,7 @@ namespace FileLiberator
|
|||
throw new Exception(errorString("Locale"));
|
||||
}
|
||||
|
||||
public bool Validate(LibraryBook libraryBook) => !libraryBook.Book.Audio_Exists;
|
||||
public override bool Validate(LibraryBook libraryBook) => !libraryBook.Book.Audio_Exists;
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,25 +11,15 @@ using FileManager;
|
|||
|
||||
namespace FileLiberator
|
||||
{
|
||||
public class DownloadPdf : IProcessable
|
||||
public class DownloadPdf : Processable
|
||||
{
|
||||
public event EventHandler<LibraryBook> Begin;
|
||||
public event EventHandler<LibraryBook> Completed;
|
||||
|
||||
public event EventHandler<string> StreamingBegin;
|
||||
public event EventHandler<DownloadProgress> StreamingProgressChanged;
|
||||
public event EventHandler<string> StreamingCompleted;
|
||||
|
||||
public event EventHandler<string> StatusUpdate;
|
||||
public event EventHandler<TimeSpan> StreamingTimeRemaining;
|
||||
|
||||
public bool Validate(LibraryBook libraryBook)
|
||||
public override bool Validate(LibraryBook libraryBook)
|
||||
=> !string.IsNullOrWhiteSpace(getdownloadUrl(libraryBook))
|
||||
&& !libraryBook.Book.PDF_Exists;
|
||||
|
||||
public async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
||||
public override async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
||||
{
|
||||
Begin?.Invoke(this, libraryBook);
|
||||
OnBegin(libraryBook);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -43,7 +33,7 @@ namespace FileLiberator
|
|||
}
|
||||
finally
|
||||
{
|
||||
Completed?.Invoke(this, libraryBook);
|
||||
OnCompleted(libraryBook);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +59,7 @@ namespace FileLiberator
|
|||
|
||||
private async Task<string> downloadPdfAsync(LibraryBook libraryBook, string proposedDownloadFilePath)
|
||||
{
|
||||
StreamingBegin?.Invoke(this, proposedDownloadFilePath);
|
||||
OnStreamingBegin(proposedDownloadFilePath);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -77,17 +67,17 @@ namespace FileLiberator
|
|||
var downloadUrl = await api.GetPdfDownloadLinkAsync(libraryBook.Book.AudibleProductId);
|
||||
|
||||
var progress = new Progress<DownloadProgress>();
|
||||
progress.ProgressChanged += (_, e) => StreamingProgressChanged?.Invoke(this, e);
|
||||
progress.ProgressChanged += (_, e) => OnStreamingProgressChanged(e);
|
||||
|
||||
var client = new HttpClient();
|
||||
|
||||
var actualDownloadedFilePath = await client.DownloadFileAsync(downloadUrl, proposedDownloadFilePath, progress);
|
||||
StatusUpdate?.Invoke(this, actualDownloadedFilePath);
|
||||
OnStatusUpdate(actualDownloadedFilePath);
|
||||
return actualDownloadedFilePath;
|
||||
}
|
||||
finally
|
||||
{
|
||||
StreamingCompleted?.Invoke(this, proposedDownloadFilePath);
|
||||
OnStreamingCompleted(proposedDownloadFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace FileLiberator
|
||||
{
|
||||
public interface IAudioDecodable : IProcessable
|
||||
public interface IAudioDecodable
|
||||
{
|
||||
event EventHandler<Action<byte[]>> RequestCoverArt;
|
||||
event EventHandler<string> TitleDiscovered;
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using DataLayer;
|
||||
using Dinah.Core.ErrorHandling;
|
||||
|
||||
namespace FileLiberator
|
||||
{
|
||||
public interface IProcessable : IStreamable
|
||||
{
|
||||
event EventHandler<LibraryBook> Begin;
|
||||
|
||||
/// <summary>General string message to display. DON'T rely on this for success, failure, or control logic</summary>
|
||||
event EventHandler<string> StatusUpdate;
|
||||
|
||||
event EventHandler<LibraryBook> Completed;
|
||||
|
||||
/// <returns>True == Valid</returns>
|
||||
bool Validate(LibraryBook libraryBook);
|
||||
|
||||
/// <returns>True == success</returns>
|
||||
Task<StatusHandler> ProcessAsync(LibraryBook libraryBook);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using DataLayer;
|
||||
using Dinah.Core;
|
||||
using Dinah.Core.ErrorHandling;
|
||||
|
||||
namespace FileLiberator
|
||||
{
|
||||
public static class IProcessableExt
|
||||
{
|
||||
// when used in foreach: stateful. deferred execution
|
||||
public static IEnumerable<LibraryBook> GetValidLibraryBooks(this IProcessable processable, IEnumerable<LibraryBook> library)
|
||||
=> library.Where(libraryBook =>
|
||||
processable.Validate(libraryBook)
|
||||
&& (libraryBook.Book.ContentType != ContentType.Episode || FileManager.Configuration.Instance.DownloadEpisodes)
|
||||
);
|
||||
|
||||
public static async Task<StatusHandler> ProcessSingleAsync(this IProcessable processable, LibraryBook libraryBook, bool validate)
|
||||
{
|
||||
if (validate && !processable.Validate(libraryBook))
|
||||
return new StatusHandler { "Validation failed" };
|
||||
|
||||
Serilog.Log.Logger.Information("Begin " + nameof(ProcessSingleAsync) + " {@DebugInfo}", new
|
||||
{
|
||||
libraryBook.Book.Title,
|
||||
libraryBook.Book.AudibleProductId,
|
||||
libraryBook.Book.Locale,
|
||||
Account = libraryBook.Account?.ToMask() ?? "[empty]"
|
||||
});
|
||||
|
||||
var status
|
||||
= (await processable.ProcessAsync(libraryBook))
|
||||
?? new StatusHandler { "Processable should never return a null status" };
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
public static async Task<StatusHandler> TryProcessAsync(this IProcessable processable, LibraryBook libraryBook)
|
||||
=> processable.Validate(libraryBook)
|
||||
? await processable.ProcessAsync(libraryBook)
|
||||
: new StatusHandler();
|
||||
}
|
||||
}
|
||||
94
FileLiberator/Processable.cs
Normal file
94
FileLiberator/Processable.cs
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using DataLayer;
|
||||
using Dinah.Core;
|
||||
using Dinah.Core.ErrorHandling;
|
||||
using Dinah.Core.Net.Http;
|
||||
|
||||
namespace FileLiberator
|
||||
{
|
||||
public abstract class Processable : IStreamable
|
||||
{
|
||||
public event EventHandler<LibraryBook> Begin;
|
||||
|
||||
/// <summary>General string message to display. DON'T rely on this for success, failure, or control logic</summary>
|
||||
public event EventHandler<string> StatusUpdate;
|
||||
|
||||
public event EventHandler<LibraryBook> Completed;
|
||||
public event EventHandler<string> StreamingBegin;
|
||||
public event EventHandler<DownloadProgress> StreamingProgressChanged;
|
||||
public event EventHandler<TimeSpan> StreamingTimeRemaining;
|
||||
public event EventHandler<string> StreamingCompleted;
|
||||
|
||||
|
||||
|
||||
// when used in foreach: stateful. deferred execution
|
||||
public IEnumerable<LibraryBook> GetValidLibraryBooks(IEnumerable<LibraryBook> library)
|
||||
=> library.Where(libraryBook =>
|
||||
Validate(libraryBook)
|
||||
&& (libraryBook.Book.ContentType != ContentType.Episode || FileManager.Configuration.Instance.DownloadEpisodes)
|
||||
);
|
||||
|
||||
public async Task<StatusHandler> ProcessSingleAsync(LibraryBook libraryBook, bool validate)
|
||||
{
|
||||
if (validate && !Validate(libraryBook))
|
||||
return new StatusHandler { "Validation failed" };
|
||||
|
||||
Serilog.Log.Logger.Information("Begin " + nameof(ProcessSingleAsync) + " {@DebugInfo}", new
|
||||
{
|
||||
libraryBook.Book.Title,
|
||||
libraryBook.Book.AudibleProductId,
|
||||
libraryBook.Book.Locale,
|
||||
Account = libraryBook.Account?.ToMask() ?? "[empty]"
|
||||
});
|
||||
|
||||
var status
|
||||
= (await ProcessAsync(libraryBook))
|
||||
?? new StatusHandler { "Processable should never return a null status" };
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
public async Task<StatusHandler> TryProcessAsync( LibraryBook libraryBook)
|
||||
=> Validate(libraryBook)
|
||||
? await ProcessAsync(libraryBook)
|
||||
: new StatusHandler();
|
||||
|
||||
/// <returns>True == Valid</returns>
|
||||
public abstract bool Validate(LibraryBook libraryBook);
|
||||
|
||||
/// <returns>True == success</returns>
|
||||
public abstract Task<StatusHandler> ProcessAsync(LibraryBook libraryBook);
|
||||
|
||||
public virtual void OnBegin(LibraryBook libraryBook)
|
||||
{
|
||||
Begin?.Invoke(this, libraryBook);
|
||||
}
|
||||
public virtual void OnCompleted(LibraryBook libraryBook)
|
||||
{
|
||||
Completed?.Invoke(this, libraryBook);
|
||||
}
|
||||
public virtual void OnStatusUpdate(string status)
|
||||
{
|
||||
StatusUpdate?.Invoke(this, status);
|
||||
}
|
||||
public virtual void OnStreamingBegin(string filePath)
|
||||
{
|
||||
StreamingBegin?.Invoke(this, filePath);
|
||||
}
|
||||
public virtual void OnStreamingCompleted(string filePath)
|
||||
{
|
||||
StreamingCompleted?.Invoke(this, filePath);
|
||||
}
|
||||
public virtual void OnStreamingProgressChanged(DownloadProgress progress)
|
||||
{
|
||||
StreamingProgressChanged?.Invoke(this, progress);
|
||||
}
|
||||
public virtual void OnStreamingTimeRemaining(TimeSpan timeRemaining)
|
||||
{
|
||||
StreamingTimeRemaining?.Invoke(this, timeRemaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue