New feature: check if upgrade available on github

This commit is contained in:
Robert McRackan 2019-12-27 22:08:43 -05:00
parent d8a0124b68
commit d9e0f1aedf
12 changed files with 284 additions and 149 deletions

View File

@ -0,0 +1,35 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Dinah.Core.Net.Http;
namespace FileLiberator
{
// frustratingly copy pasta from DownloadableBase and DownloadPdf
public class DownloadFile : IDownloadable
{
public event EventHandler<string> DownloadBegin;
public event EventHandler<DownloadProgress> DownloadProgressChanged;
public event EventHandler<string> DownloadCompleted;
public async Task<string> PerformDownloadFileAsync(string downloadUrl, string proposedDownloadFilePath)
{
var client = new HttpClient();
var progress = new Progress<DownloadProgress>();
progress.ProgressChanged += (_, e) => DownloadProgressChanged?.Invoke(this, e);
DownloadBegin?.Invoke(this, proposedDownloadFilePath);
try
{
var actualDownloadedFilePath = await client.DownloadFileAsync(downloadUrl, proposedDownloadFilePath, progress);
return actualDownloadedFilePath;
}
finally
{
DownloadCompleted?.Invoke(this, proposedDownloadFilePath);
}
}
}
}

View File

@ -16,9 +16,6 @@ namespace FileLiberator
=> !string.IsNullOrWhiteSpace(getdownloadUrl(libraryBook)) => !string.IsNullOrWhiteSpace(getdownloadUrl(libraryBook))
&& !AudibleFileStorage.PDF.Exists(libraryBook.Book.AudibleProductId); && !AudibleFileStorage.PDF.Exists(libraryBook.Book.AudibleProductId);
private static string getdownloadUrl(LibraryBook libraryBook)
=> libraryBook?.Book?.Supplements?.FirstOrDefault()?.Url;
public override async Task<StatusHandler> ProcessItemAsync(LibraryBook libraryBook) public override async Task<StatusHandler> ProcessItemAsync(LibraryBook libraryBook)
{ {
var proposedDownloadFilePath = getProposedDownloadFilePath(libraryBook); var proposedDownloadFilePath = getProposedDownloadFilePath(libraryBook);
@ -26,6 +23,11 @@ namespace FileLiberator
return verifyDownload(libraryBook); return verifyDownload(libraryBook);
} }
private static StatusHandler verifyDownload(LibraryBook libraryBook)
=> !AudibleFileStorage.PDF.Exists(libraryBook.Book.AudibleProductId)
? new StatusHandler { "Downloaded PDF cannot be found" }
: new StatusHandler();
private static string getProposedDownloadFilePath(LibraryBook libraryBook) private static string getProposedDownloadFilePath(LibraryBook libraryBook)
{ {
// if audio file exists, get it's dir. else return base Book dir // if audio file exists, get it's dir. else return base Book dir
@ -39,15 +41,15 @@ namespace FileLiberator
private async Task downloadPdfAsync(LibraryBook libraryBook, string proposedDownloadFilePath) private async Task downloadPdfAsync(LibraryBook libraryBook, string proposedDownloadFilePath)
{ {
var downloadUrl = getdownloadUrl(libraryBook);
var client = new HttpClient(); var client = new HttpClient();
var actualDownloadedFilePath = await PerformDownloadAsync( var actualDownloadedFilePath = await PerformDownloadAsync(
proposedDownloadFilePath, proposedDownloadFilePath,
(p) => client.DownloadFileAsync(getdownloadUrl(libraryBook), proposedDownloadFilePath, p)); (p) => client.DownloadFileAsync(downloadUrl, proposedDownloadFilePath, p));
} }
private static StatusHandler verifyDownload(LibraryBook libraryBook) private static string getdownloadUrl(LibraryBook libraryBook)
=> !AudibleFileStorage.PDF.Exists(libraryBook.Book.AudibleProductId) => libraryBook?.Book?.Supplements?.FirstOrDefault()?.Url;
? new StatusHandler { "Downloaded PDF cannot be found" }
: new StatusHandler();
} }
} }

View File

@ -6,7 +6,7 @@ using Dinah.Core.Net.Http;
namespace FileLiberator namespace FileLiberator
{ {
public abstract class DownloadableBase : IDownloadable public abstract class DownloadableBase : IDownloadableProcessable
{ {
public event EventHandler<LibraryBook> Begin; public event EventHandler<LibraryBook> Begin;
public event EventHandler<LibraryBook> Completed; public event EventHandler<LibraryBook> Completed;

View File

@ -3,7 +3,7 @@ using Dinah.Core.Net.Http;
namespace FileLiberator namespace FileLiberator
{ {
public interface IDownloadable : IProcessable public interface IDownloadable
{ {
event EventHandler<string> DownloadBegin; event EventHandler<string> DownloadBegin;
event EventHandler<DownloadProgress> DownloadProgressChanged; event EventHandler<DownloadProgress> DownloadProgressChanged;

View File

@ -0,0 +1,4 @@
namespace FileLiberator
{
public interface IDownloadableProcessable : IDownloadable, IProcessable { }
}

4
LibationLauncher/.msbump Normal file
View File

@ -0,0 +1,4 @@
{
"//": "https://github.com/BalassaMarton/MSBump",
BumpRevision: true
}

View File

@ -1,4 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> <?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
@ -11,8 +12,18 @@
<PublishReadyToRun>true</PublishReadyToRun> <PublishReadyToRun>true</PublishReadyToRun>
<!-- <PublishSingleFile>true</PublishSingleFile> --> <!-- <PublishSingleFile>true</PublishSingleFile> -->
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <RuntimeIdentifier>win-x64</RuntimeIdentifier>
<Version>3.1.0.50</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="MSBump" Version="2.3.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Octokit" Version="0.36.0" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\LibationWinForms\LibationWinForms.csproj" /> <ProjectReference Include="..\LibationWinForms\LibationWinForms.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -1,7 +1,8 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using Dinah.Core.Logging;
using FileManager; using FileManager;
using LibationWinForms; using LibationWinForms;
using LibationWinForms.Dialogs; using LibationWinForms.Dialogs;
@ -21,7 +22,12 @@ namespace LibationLauncher
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
createSettings(); createSettings();
initLogging();
ensureLoggingConfig();
ensureSerilogConfig();
configureLogging();
checkForUpdate();
logStartupState();
Application.Run(new Form1()); Application.Run(new Form1());
} }
@ -71,47 +77,11 @@ namespace LibationLauncher
&& !string.IsNullOrWhiteSpace(config.DownloadsInProgressEnum) && !string.IsNullOrWhiteSpace(config.DownloadsInProgressEnum)
&& !string.IsNullOrWhiteSpace(config.DecryptInProgressEnum); && !string.IsNullOrWhiteSpace(config.DecryptInProgressEnum);
private static void initLogging() private static string defaultLoggingLevel { get; } = "Information";
private static void ensureLoggingConfig()
{ {
var config = Configuration.Instance; var config = Configuration.Instance;
ensureLoggingConfig(config);
ensureSerilogConfig(config);
// override path. always use current libation files
var logPath = Path.Combine(Configuration.Instance.LibationFiles, "Log.log");
config.SetWithJsonPath("Serilog.WriteTo[1].Args", "path", logPath);
//// hack which achieves the same
//configuration["Serilog:WriteTo:1:Args:path"] = logPath;
// CONFIGURATION-DRIVEN (json)
var configuration = new ConfigurationBuilder()
.AddJsonFile(config.SettingsJsonPath)
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
//// MANUAL HARD CODED
//Log.Logger = new LoggerConfiguration()
// .Enrich.WithCaller()
// .MinimumLevel.Information()
// .WriteTo.File(logPath,
// rollingInterval: RollingInterval.Month,
// outputTemplate: code_outputTemplate)
// .CreateLogger();
Log.Logger.Information("Begin Libation");
// .Here() captures debug info via System.Runtime.CompilerServices attributes. Warning: expensive
//var withLineNumbers_outputTemplate = "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}in method {MemberName} at {FilePath}:{LineNumber}{NewLine}{Exception}{NewLine}";
//Log.Logger.Here().Debug("Begin Libation. Debug with line numbers");
}
private static string defaultLoggingLevel { get; } = "Information";
private static void ensureLoggingConfig(Configuration config)
{
if (config.GetObject("Logging") != null) if (config.GetObject("Logging") != null)
return; return;
@ -129,8 +99,10 @@ namespace LibationLauncher
config.SetObject("Logging", loggingObj); config.SetObject("Logging", loggingObj);
} }
private static void ensureSerilogConfig(Configuration config) private static void ensureSerilogConfig()
{ {
var config = Configuration.Instance;
if (config.GetObject("Serilog") != null) if (config.GetObject("Serilog") != null)
return; return;
@ -184,5 +156,101 @@ namespace LibationLauncher
}; };
config.SetObject("Serilog", serilogObj); config.SetObject("Serilog", serilogObj);
} }
private static void configureLogging()
{
var config = Configuration.Instance;
// override path. always use current libation files
var logPath = Path.Combine(Configuration.Instance.LibationFiles, "Log.log");
config.SetWithJsonPath("Serilog.WriteTo[1].Args", "path", logPath);
//// hack which achieves the same
//configuration["Serilog:WriteTo:1:Args:path"] = logPath;
// CONFIGURATION-DRIVEN (json)
var configuration = new ConfigurationBuilder()
.AddJsonFile(config.SettingsJsonPath)
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
//// MANUAL HARD CODED
//Log.Logger = new LoggerConfiguration()
// // requires: using Dinah.Core.Logging;
// .Enrich.WithCaller()
// .MinimumLevel.Information()
// .WriteTo.File(logPath,
// rollingInterval: RollingInterval.Month,
// outputTemplate: code_outputTemplate)
// .CreateLogger();
// .Here() captures debug info via System.Runtime.CompilerServices attributes. Warning: expensive
//var withLineNumbers_outputTemplate = "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}in method {MemberName} at {FilePath}:{LineNumber}{NewLine}{Exception}{NewLine}";
//Log.Logger.Here().Debug("Begin Libation. Debug with line numbers");
}
private static event Action cheating;
private static void checkForUpdate()
{
try
{
var gitHubClient = new Octokit.GitHubClient(new Octokit.ProductHeaderValue("Libation"));
// https://octokitnet.readthedocs.io/en/latest/releases/
var releases = gitHubClient.Repository.Release.GetAll("rmcrackan", "Libation").GetAwaiter().GetResult();
var latest = releases.First(r => !r.Draft);
var latestVersionString = latest.TagName.Trim('v');
if (!Version.TryParse(latestVersionString, out var latestRelease))
return;
// we're up to date
if (latestRelease <= BuildVersion)
return;
// we have an update
var zip = latest.Assets.FirstOrDefault(a => a.BrowserDownloadUrl.EndsWith(".zip"));
var zipUrl = zip?.BrowserDownloadUrl;
if (zipUrl is null)
{
MessageBox.Show(latest.HtmlUrl, "New version available");
return;
}
var result = MessageBox.Show($"New version available @ {latest.HtmlUrl}\r\nDownload the zip file?", "New version available", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
if (result != DialogResult.Yes)
return;
using var fileSelector = new SaveFileDialog { FileName = zip.Name, Filter = "Zip Files (*.zip)|*.zip|All files (*.*)|*.*" };
if (fileSelector.ShowDialog() != DialogResult.OK)
return;
var selectedPath = fileSelector.FileName;
try
{
LibationWinForms.BookLiberation.ProcessorAutomationController.DownloadFileAsync(zipUrl, selectedPath).GetAwaiter().GetResult();
MessageBox.Show($"File downloaded");
}
catch (Exception ex)
{
MessageBox.Show($"ERROR: {ex.Message}\r\n{ex.StackTrace}");
}
}
catch (Exception ex)
{
MessageBox.Show($"Error checking for update. ERROR: {ex.Message}\r\n{ex.StackTrace}");
}
}
private static void logStartupState()
{
Log.Logger.Information("Begin Libation");
Log.Logger.Information($"Version: {BuildVersion}");
}
private static Version BuildVersion => System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
} }
} }

View File

@ -33,13 +33,13 @@ namespace LibationWinForms.BookLiberation
} }
#region timer #region timer
Timer timer = new Timer { Interval = 1000 }; private Timer timer { get; } = new Timer { Interval = 1000 };
private void DownloadForm_Load(object sender, EventArgs e) private void DownloadForm_Load(object sender, EventArgs e)
{ {
timer.Tick += new EventHandler(timer_Tick); timer.Tick += new EventHandler(timer_Tick);
timer.Start(); timer.Start();
} }
DateTime lastDownloadProgress = DateTime.Now; private DateTime lastDownloadProgress = DateTime.Now;
private void timer_Tick(object sender, EventArgs e) private void timer_Tick(object sender, EventArgs e)
{ {
// if no update in the last 30 seconds, display frozen label // if no update in the last 30 seconds, display frozen label

View File

@ -6,15 +6,28 @@ using FileLiberator;
namespace LibationWinForms.BookLiberation namespace LibationWinForms.BookLiberation
{ {
// matches a file processor with a form
public static class ProcessorAutomationController public static class ProcessorAutomationController
{ {
// public static async Task BackupSingleBookAsync(string productId, EventHandler<LibraryBook> completedAction = null)
// these utility methods ensure proper wiring {
// 1) we can't forget to do it var backupBook = getWiredUpBackupBook(completedAction);
// 2) we can't accidentally do it mult times becaues we lost track of complexity
// var automatedBackupsForm = attachToBackupsForm(backupBook);
public static BackupBook GetWiredUpBackupBook(EventHandler<LibraryBook> completedAction = null) automatedBackupsForm.KeepGoingVisible = false;
await runSingleBackupAsync(backupBook, automatedBackupsForm, productId);
}
public static async Task BackupAllBooksAsync(EventHandler<LibraryBook> completedAction = null)
{
var backupBook = getWiredUpBackupBook(completedAction);
var automatedBackupsForm = attachToBackupsForm(backupBook);
await runBackupLoopAsync(backupBook, automatedBackupsForm);
}
private static BackupBook getWiredUpBackupBook(EventHandler<LibraryBook> completedAction)
{ {
var backupBook = new BackupBook(); var backupBook = new BackupBook();
@ -32,7 +45,65 @@ namespace LibationWinForms.BookLiberation
return backupBook; return backupBook;
} }
public static DownloadPdf GetWiredUpDownloadPdf(EventHandler<LibraryBook> completedAction = null) private static AutomatedBackupsForm attachToBackupsForm(BackupBook backupBook)
{
#region create form
var automatedBackupsForm = new AutomatedBackupsForm();
#endregion
#region define how model actions will affect form behavior
void downloadBookBegin(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Download Step, Begin: {libraryBook.Book}");
void statusUpdate(object _, string str) => automatedBackupsForm.AppendText("- " + str);
void downloadBookCompleted(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Download Step, Completed: {libraryBook.Book}");
void decryptBookBegin(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Decrypt Step, Begin: {libraryBook.Book}");
// extra line after book is completely finished
void decryptBookCompleted(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Decrypt Step, Completed: {libraryBook.Book}{Environment.NewLine}");
void downloadPdfBegin(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"PDF Step, Begin: {libraryBook.Book}");
// extra line after book is completely finished
void downloadPdfCompleted(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"PDF Step, Completed: {libraryBook.Book}{Environment.NewLine}");
#endregion
#region subscribe new form to model's events
backupBook.DownloadBook.Begin += downloadBookBegin;
backupBook.DownloadBook.StatusUpdate += statusUpdate;
backupBook.DownloadBook.Completed += downloadBookCompleted;
backupBook.DecryptBook.Begin += decryptBookBegin;
backupBook.DecryptBook.StatusUpdate += statusUpdate;
backupBook.DecryptBook.Completed += decryptBookCompleted;
backupBook.DownloadPdf.Begin += downloadPdfBegin;
backupBook.DownloadPdf.StatusUpdate += statusUpdate;
backupBook.DownloadPdf.Completed += downloadPdfCompleted;
#endregion
#region when form closes, unsubscribe from model's events
// unsubscribe so disposed forms aren't still trying to receive notifications
automatedBackupsForm.FormClosing += (_, __) =>
{
backupBook.DownloadBook.Begin -= downloadBookBegin;
backupBook.DownloadBook.StatusUpdate -= statusUpdate;
backupBook.DownloadBook.Completed -= downloadBookCompleted;
backupBook.DecryptBook.Begin -= decryptBookBegin;
backupBook.DecryptBook.StatusUpdate -= statusUpdate;
backupBook.DecryptBook.Completed -= decryptBookCompleted;
backupBook.DownloadPdf.Begin -= downloadPdfBegin;
backupBook.DownloadPdf.StatusUpdate -= statusUpdate;
backupBook.DownloadPdf.Completed -= downloadPdfCompleted;
};
#endregion
return automatedBackupsForm;
}
public static async Task BackupAllPdfsAsync(EventHandler<LibraryBook> completedAction = null)
{
var downloadPdf = getWiredUpDownloadPdf(completedAction);
var automatedBackupsForm = attachToBackupsForm(downloadPdf);
await runBackupLoopAsync(downloadPdf, automatedBackupsForm);
}
private static DownloadPdf getWiredUpDownloadPdf(EventHandler<LibraryBook> completedAction)
{ {
var downloadPdf = new DownloadPdf(); var downloadPdf = new DownloadPdf();
@ -44,8 +115,25 @@ namespace LibationWinForms.BookLiberation
return downloadPdf; return downloadPdf;
} }
public static async Task DownloadFileAsync(string url, string destination)
{
var downloadFile = new DownloadFile();
// frustratingly copy pasta from wireUpEvents(IDownloadable downloadable) due to Completed being EventHandler<LibraryBook>
var downloadDialog = new DownloadForm();
downloadFile.DownloadBegin += (_, str) =>
{
downloadDialog.UpdateFilename(str);
downloadDialog.Show();
};
downloadFile.DownloadProgressChanged += (_, progress) => downloadDialog.DownloadProgressChanged(progress.BytesReceived, progress.TotalBytesToReceive.Value);
downloadFile.DownloadCompleted += (_, __) => downloadDialog.Close();
await downloadFile.PerformDownloadFileAsync(url, destination);
}
// subscribed to Begin event because a new form should be created+processed+closed on each iteration // subscribed to Begin event because a new form should be created+processed+closed on each iteration
private static void wireUpEvents(IDownloadable downloadable) private static void wireUpEvents(IDownloadableProcessable downloadable)
{ {
#region create form #region create form
var downloadDialog = new DownloadForm(); var downloadDialog = new DownloadForm();
@ -156,13 +244,7 @@ namespace LibationWinForms.BookLiberation
#endregion #endregion
} }
public static async Task RunAutomaticDownloadAsync(IDownloadable downloadable) private static AutomatedBackupsForm attachToBackupsForm(IDownloadableProcessable downloadable)
{
AutomatedBackupsForm automatedBackupsForm = attachToBackupsForm(downloadable);
await runBackupLoopAsync(downloadable, automatedBackupsForm);
}
private static AutomatedBackupsForm attachToBackupsForm(IDownloadable downloadable)
{ {
#region create form #region create form
var automatedBackupsForm = new AutomatedBackupsForm(); var automatedBackupsForm = new AutomatedBackupsForm();
@ -194,68 +276,6 @@ namespace LibationWinForms.BookLiberation
return automatedBackupsForm; return automatedBackupsForm;
} }
public static async Task RunAutomaticBackupAsync(BackupBook backupBook)
{
var automatedBackupsForm = attachToBackupsForm(backupBook);
await runBackupLoopAsync(backupBook, automatedBackupsForm);
}
public static async Task RunSingleBackupAsync(BackupBook backupBook, string productId)
{
var automatedBackupsForm = attachToBackupsForm(backupBook);
automatedBackupsForm.KeepGoingVisible = false;
await runSingleBackupAsync(backupBook, automatedBackupsForm, productId);
}
private static AutomatedBackupsForm attachToBackupsForm(BackupBook backupBook)
{
#region create form
var automatedBackupsForm = new AutomatedBackupsForm();
#endregion
#region define how model actions will affect form behavior
void downloadBookBegin(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Download Step, Begin: {libraryBook.Book}");
void statusUpdate(object _, string str) => automatedBackupsForm.AppendText("- " + str);
void downloadBookCompleted(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Download Step, Completed: {libraryBook.Book}");
void decryptBookBegin(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Decrypt Step, Begin: {libraryBook.Book}");
// extra line after book is completely finished
void decryptBookCompleted(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"Decrypt Step, Completed: {libraryBook.Book}{Environment.NewLine}");
void downloadPdfBegin(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"PDF Step, Begin: {libraryBook.Book}");
// extra line after book is completely finished
void downloadPdfCompleted(object _, LibraryBook libraryBook) => automatedBackupsForm.AppendText($"PDF Step, Completed: {libraryBook.Book}{Environment.NewLine}");
#endregion
#region subscribe new form to model's events
backupBook.DownloadBook.Begin += downloadBookBegin;
backupBook.DownloadBook.StatusUpdate += statusUpdate;
backupBook.DownloadBook.Completed += downloadBookCompleted;
backupBook.DecryptBook.Begin += decryptBookBegin;
backupBook.DecryptBook.StatusUpdate += statusUpdate;
backupBook.DecryptBook.Completed += decryptBookCompleted;
backupBook.DownloadPdf.Begin += downloadPdfBegin;
backupBook.DownloadPdf.StatusUpdate += statusUpdate;
backupBook.DownloadPdf.Completed += downloadPdfCompleted;
#endregion
#region when form closes, unsubscribe from model's events
// unsubscribe so disposed forms aren't still trying to receive notifications
automatedBackupsForm.FormClosing += (_, __) =>
{
backupBook.DownloadBook.Begin -= downloadBookBegin;
backupBook.DownloadBook.StatusUpdate -= statusUpdate;
backupBook.DownloadBook.Completed -= downloadBookCompleted;
backupBook.DecryptBook.Begin -= decryptBookBegin;
backupBook.DecryptBook.StatusUpdate -= statusUpdate;
backupBook.DecryptBook.Completed -= decryptBookCompleted;
backupBook.DownloadPdf.Begin -= downloadPdfBegin;
backupBook.DownloadPdf.StatusUpdate -= statusUpdate;
backupBook.DownloadPdf.Completed -= downloadPdfCompleted;
};
#endregion
return automatedBackupsForm;
}
// automated backups looper feels like a composible IProcessable: logic, UI, begin + process child + end // automated backups looper feels like a composible IProcessable: logic, UI, begin + process child + end
// however the process step doesn't follow the pattern: Validate(product) + Process(product) // however the process step doesn't follow the pattern: Validate(product) + Process(product)
private static async Task runBackupLoopAsync(IProcessable processable, AutomatedBackupsForm automatedBackupsForm) private static async Task runBackupLoopAsync(IProcessable processable, AutomatedBackupsForm automatedBackupsForm)

View File

@ -112,7 +112,7 @@ namespace LibationWinForms
enum AudioFileState { full, aax, none } enum AudioFileState { full, aax, none }
private void setBookBackupCounts(IEnumerable<Book> books) private void setBookBackupCounts(IEnumerable<Book> books)
{ {
AudioFileState getAudioFileState(string productId) static AudioFileState getAudioFileState(string productId)
{ {
if (AudibleFileStorage.Audio.Exists(productId)) if (AudibleFileStorage.Audio.Exists(productId))
return AudioFileState.full; return AudioFileState.full;
@ -237,16 +237,10 @@ namespace LibationWinForms
#region liberate menu #region liberate menu
private async void beginBookBackupsToolStripMenuItem_Click(object sender, EventArgs e) private async void beginBookBackupsToolStripMenuItem_Click(object sender, EventArgs e)
{ => await BookLiberation.ProcessorAutomationController.BackupAllBooksAsync(updateGridRow);
var backupBook = BookLiberation.ProcessorAutomationController.GetWiredUpBackupBook(updateGridRow);
await BookLiberation.ProcessorAutomationController.RunAutomaticBackupAsync(backupBook);
}
private async void beginPdfBackupsToolStripMenuItem_Click(object sender, EventArgs e) private async void beginPdfBackupsToolStripMenuItem_Click(object sender, EventArgs e)
{ => await BookLiberation.ProcessorAutomationController.BackupAllPdfsAsync(updateGridRow);
var downloadPdf = BookLiberation.ProcessorAutomationController.GetWiredUpDownloadPdf(updateGridRow);
await BookLiberation.ProcessorAutomationController.RunAutomaticDownloadAsync(downloadPdf);
}
private void updateGridRow(object _, LibraryBook libraryBook) => currProductsGrid.RefreshRow(libraryBook.Book.AudibleProductId); private void updateGridRow(object _, LibraryBook libraryBook) => currProductsGrid.RefreshRow(libraryBook.Book.AudibleProductId);
#endregion #endregion

View File

@ -174,18 +174,15 @@ namespace LibationWinForms
var productId = getGridEntry(e.RowIndex).GetBook().AudibleProductId; var productId = getGridEntry(e.RowIndex).GetBook().AudibleProductId;
// if liberated, open explorer to file // not liberated: liberate
if (FileManager.AudibleFileStorage.Audio.Exists(productId)) if (!FileManager.AudibleFileStorage.Audio.Exists(productId))
await BookLiberation.ProcessorAutomationController.BackupSingleBookAsync(productId, (_, __) => RefreshRow(productId));
// liberated: open explorer to file
else
{ {
var filePath = FileManager.AudibleFileStorage.Audio.GetPath(productId); var filePath = FileManager.AudibleFileStorage.Audio.GetPath(productId);
System.Diagnostics.Process.Start("explorer.exe", $"/select, \"{filePath}\""); System.Diagnostics.Process.Start("explorer.exe", $"/select, \"{filePath}\"");
} }
// else liberate
else
{
var backupBook = BookLiberation.ProcessorAutomationController.GetWiredUpBackupBook((_, __) => RefreshRow(productId));
await BookLiberation.ProcessorAutomationController.RunSingleBackupAsync(backupBook, productId);
}
} }
#endregion #endregion