Populate new values for book tracking state. Not using them yet, but getting much closer

This commit is contained in:
Robert McRackan 2021-07-28 16:05:00 -04:00
parent 8de8e50829
commit 5c6b5c0af2
8 changed files with 91 additions and 41 deletions

View File

@ -41,7 +41,8 @@ namespace ApplicationServices
// However, it comes with a scary warning when used with EntityFrameworkCore which I'm not yet ready to implement: // However, it comes with a scary warning when used with EntityFrameworkCore which I'm not yet ready to implement:
// https://github.com/RehanSaeed/Serilog.Exceptions // https://github.com/RehanSaeed/Serilog.Exceptions
// work-around: use 3rd param. don't just put exception object in 3rd param -- info overload: stack trace, etc // work-around: use 3rd param. don't just put exception object in 3rd param -- info overload: stack trace, etc
Log.Logger.Error(lfEx, "Error importing library. Login failed. {@DebugInfo}", new { Log.Logger.Error(lfEx, "Error importing library. Login failed. {@DebugInfo}", new
{
lfEx.RequestUrl, lfEx.RequestUrl,
ResponseStatusCodeNumber = (int)lfEx.ResponseStatusCode, ResponseStatusCodeNumber = (int)lfEx.ResponseStatusCode,
ResponseStatusCodeDesc = lfEx.ResponseStatusCode, ResponseStatusCodeDesc = lfEx.ResponseStatusCode,
@ -100,10 +101,12 @@ namespace ApplicationServices
return newCount; return newCount;
} }
public static int UpdateTags(this LibationContext context, Book book, string newTags) public static int UpdateTags(Book book, string newTags)
{ {
try try
{ {
using var context = DbContexts.GetContext();
var udi = book.UserDefinedItem; var udi = book.UserDefinedItem;
// Attach() NoTracking entities before SaveChanges() // Attach() NoTracking entities before SaveChanges()
@ -122,5 +125,52 @@ namespace ApplicationServices
throw; throw;
} }
} }
public static int UpdateBook(LibraryBook libraryBook, LiberatedStatus liberatedStatus, string finalAudioPath)
{
try
{
using var context = DbContexts.GetContext();
var udi = libraryBook.Book.UserDefinedItem;
// Attach() NoTracking entities before SaveChanges()
udi.BookStatus = liberatedStatus;
udi.BookLocation = finalAudioPath;
context.Attach(udi).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
var qtyChanges = context.SaveChanges();
if (qtyChanges > 0)
SearchEngineCommands.UpdateLiberatedStatus(libraryBook.Book);
return qtyChanges;
}
catch (Exception ex)
{
Log.Logger.Error(ex, "Error updating tags");
throw;
}
}
public static int UpdatePdf(LibraryBook libraryBook, LiberatedStatus liberatedStatus)
{
try
{
using var context = DbContexts.GetContext();
var udi = libraryBook.Book.UserDefinedItem;
// Attach() NoTracking entities before SaveChanges()
udi.PdfStatus = liberatedStatus;
context.Attach(udi).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
var qtyChanges = context.SaveChanges();
return qtyChanges;
}
catch (Exception ex)
{
Log.Logger.Error(ex, "Error updating tags");
throw;
}
}
} }
} }

View File

@ -220,8 +220,11 @@ namespace DataLayer
ArgumentValidator.EnsureNotNullOrWhiteSpace(url, nameof(url)); ArgumentValidator.EnsureNotNullOrWhiteSpace(url, nameof(url));
if (!_supplements.Any(s => url.EqualsInsensitive(url))) if (_supplements.Any(s => url.EqualsInsensitive(url)))
return;
_supplements.Add(new Supplement(this, url)); _supplements.Add(new Supplement(this, url));
UserDefinedItem.PdfStatus ??= LiberatedStatus.NotLiberated;
} }
#endregion #endregion

View File

@ -20,7 +20,7 @@ namespace FileLiberator
public event EventHandler<string> StatusUpdate; public event EventHandler<string> StatusUpdate;
public event EventHandler<LibraryBook> Completed; public event EventHandler<LibraryBook> Completed;
public DownloadDecryptBook DecryptBook { get; } = new DownloadDecryptBook(); public DownloadDecryptBook DownloadDecryptBook { get; } = new DownloadDecryptBook();
public DownloadPdf DownloadPdf { get; } = new DownloadPdf(); public DownloadPdf DownloadPdf { get; } = new DownloadPdf();
public bool Validate(LibraryBook libraryBook) public bool Validate(LibraryBook libraryBook)
@ -35,7 +35,7 @@ namespace FileLiberator
try try
{ {
{ {
var statusHandler = await DecryptBook.TryProcessAsync(libraryBook); var statusHandler = await DownloadDecryptBook.TryProcessAsync(libraryBook);
if (statusHandler.HasErrors) if (statusHandler.HasErrors)
return statusHandler; return statusHandler;
} }

View File

@ -1,15 +1,14 @@
using DataLayer; using System;
using Dinah.Core;
using Dinah.Core.ErrorHandling;
using FileManager;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using AaxDecrypter; using AaxDecrypter;
using AudibleApi; using AudibleApi;
using DataLayer;
using Dinah.Core;
using Dinah.Core.ErrorHandling;
using FileManager;
namespace FileLiberator namespace FileLiberator
{ {
@ -51,6 +50,11 @@ namespace FileLiberator
if (!finalAudioExists) if (!finalAudioExists)
return new StatusHandler { "Cannot find final audio file after decryption" }; return new StatusHandler { "Cannot find final audio file after decryption" };
// GetPath() is very cheap when file exists
var finalAudioPath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId);
// only need to update if success. if failure, it will remain at 0 == NotLiberated
ApplicationServices.LibraryCommands.UpdateBook(libraryBook, LiberatedStatus.Liberated, finalAudioPath);
return new StatusHandler(); return new StatusHandler();
} }
finally finally

View File

@ -1,4 +1,6 @@
using System.IO; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -19,7 +21,12 @@ namespace FileLiberator
{ {
var proposedDownloadFilePath = getProposedDownloadFilePath(libraryBook); var proposedDownloadFilePath = getProposedDownloadFilePath(libraryBook);
await downloadPdfAsync(libraryBook, proposedDownloadFilePath); await downloadPdfAsync(libraryBook, proposedDownloadFilePath);
return verifyDownload(libraryBook); var result = verifyDownload(libraryBook);
var liberatedStatus = result.IsSuccess ? LiberatedStatus.Liberated : LiberatedStatus.NotLiberated;
ApplicationServices.LibraryCommands.UpdatePdf(libraryBook, liberatedStatus);
return result;
} }
private static string getProposedDownloadFilePath(LibraryBook libraryBook) private static string getProposedDownloadFilePath(LibraryBook libraryBook)

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using ApplicationServices; using ApplicationServices;

View File

@ -86,7 +86,6 @@ namespace LibationWinForms.BookLiberation
var convertBook = new ConvertToMp3(); var convertBook = new ConvertToMp3();
convertBook.Begin += (_, l) => wireUpEvents(convertBook, l, "Converting"); convertBook.Begin += (_, l) => wireUpEvents(convertBook, l, "Converting");
convertBook.Completed += updateLiberatedStatus;
var automatedBackupsForm = new AutomatedBackupsForm(); var automatedBackupsForm = new AutomatedBackupsForm();
@ -104,36 +103,24 @@ namespace LibationWinForms.BookLiberation
convertBook.Begin -= convertBookBegin; convertBook.Begin -= convertBookBegin;
convertBook.StatusUpdate -= statusUpdate; convertBook.StatusUpdate -= statusUpdate;
convertBook.Completed -= convertBookCompleted; convertBook.Completed -= convertBookCompleted;
convertBook.Completed -= updateLiberatedStatus;
} }
private static BackupBook getWiredUpBackupBook(EventHandler<LibraryBook> completedAction) private static BackupBook getWiredUpBackupBook(EventHandler<LibraryBook> completedAction)
{ {
var backupBook = new BackupBook(); var backupBook = new BackupBook();
backupBook.DecryptBook.Begin += (_, l) => wireUpEvents(backupBook.DecryptBook, l); backupBook.DownloadDecryptBook.Begin += (_, l) => wireUpEvents(backupBook.DownloadDecryptBook, l);
backupBook.DownloadPdf.Begin += (_, __) => wireUpEvents(backupBook.DownloadPdf); backupBook.DownloadPdf.Begin += (_, __) => wireUpEvents(backupBook.DownloadPdf);
// must occur before completedAction. A common use case is:
// - filter by -liberated
// - liberate only that book
// completedAction is to refresh grid
// - want to see that book disappear from grid
// also for this to work, updateIsLiberated can NOT be async
backupBook.DecryptBook.Completed += updateLiberatedStatus;
backupBook.DownloadPdf.Completed += updateLiberatedStatus;
if (completedAction != null) if (completedAction != null)
{ {
backupBook.DecryptBook.Completed += completedAction; backupBook.DownloadDecryptBook.Completed += completedAction;
backupBook.DownloadPdf.Completed += completedAction; backupBook.DownloadPdf.Completed += completedAction;
} }
return backupBook; return backupBook;
} }
private static void updateLiberatedStatus(object sender, LibraryBook e) => ApplicationServices.SearchEngineCommands.UpdateLiberatedStatus(e.Book);
private static (Action unsubscribeEvents, LogMe) attachToBackupsForm(BackupBook backupBook, AutomatedBackupsForm automatedBackupsForm = null) private static (Action unsubscribeEvents, LogMe) attachToBackupsForm(BackupBook backupBook, AutomatedBackupsForm automatedBackupsForm = null)
{ {
#region create logger #region create logger
@ -151,9 +138,9 @@ namespace LibationWinForms.BookLiberation
#endregion #endregion
#region subscribe new form to model's events #region subscribe new form to model's events
backupBook.DecryptBook.Begin += decryptBookBegin; backupBook.DownloadDecryptBook.Begin += decryptBookBegin;
backupBook.DecryptBook.StatusUpdate += statusUpdate; backupBook.DownloadDecryptBook.StatusUpdate += statusUpdate;
backupBook.DecryptBook.Completed += decryptBookCompleted; backupBook.DownloadDecryptBook.Completed += decryptBookCompleted;
backupBook.DownloadPdf.Begin += downloadPdfBegin; backupBook.DownloadPdf.Begin += downloadPdfBegin;
backupBook.DownloadPdf.StatusUpdate += statusUpdate; backupBook.DownloadPdf.StatusUpdate += statusUpdate;
backupBook.DownloadPdf.Completed += downloadPdfCompleted; backupBook.DownloadPdf.Completed += downloadPdfCompleted;
@ -163,9 +150,9 @@ namespace LibationWinForms.BookLiberation
// unsubscribe so disposed forms aren't still trying to receive notifications // unsubscribe so disposed forms aren't still trying to receive notifications
Action unsubscribe = () => Action unsubscribe = () =>
{ {
backupBook.DecryptBook.Begin -= decryptBookBegin; backupBook.DownloadDecryptBook.Begin -= decryptBookBegin;
backupBook.DecryptBook.StatusUpdate -= statusUpdate; backupBook.DownloadDecryptBook.StatusUpdate -= statusUpdate;
backupBook.DecryptBook.Completed -= decryptBookCompleted; backupBook.DownloadDecryptBook.Completed -= decryptBookCompleted;
backupBook.DownloadPdf.Begin -= downloadPdfBegin; backupBook.DownloadPdf.Begin -= downloadPdfBegin;
backupBook.DownloadPdf.StatusUpdate -= statusUpdate; backupBook.DownloadPdf.StatusUpdate -= statusUpdate;
backupBook.DownloadPdf.Completed -= downloadPdfCompleted; backupBook.DownloadPdf.Completed -= downloadPdfCompleted;
@ -497,6 +484,7 @@ $@" Title: {libraryBook.Book.Title}
if (dialogResult == CreateSkipFileResult) if (dialogResult == CreateSkipFileResult)
{ {
ApplicationServices.LibraryCommands.UpdateBook(libraryBook, LiberatedStatus.Error, null);
var path = FileManager.AudibleFileStorage.Audio.CreateSkipFile(libraryBook.Book.Title, libraryBook.Book.AudibleProductId, logMessage); var path = FileManager.AudibleFileStorage.Audio.CreateSkipFile(libraryBook.Book.Title, libraryBook.Book.AudibleProductId, logMessage);
LogMe.Info($@" LogMe.Info($@"
Created new 'skip' file Created new 'skip' file

View File

@ -36,8 +36,6 @@ namespace LibationWinForms
// alias // alias
private DataGridView dataGridView => gridEntryDataGridView; private DataGridView dataGridView => gridEntryDataGridView;
private LibationContext context;
public ProductsGrid() public ProductsGrid()
{ {
InitializeComponent(); InitializeComponent();
@ -45,7 +43,6 @@ namespace LibationWinForms
addLiberateButtons(); addLiberateButtons();
addEditTagsButtons(); addEditTagsButtons();
formatColumns(); formatColumns();
Disposed += (_, __) => context?.Dispose();
manageLiveImageUpdateSubscriptions(); manageLiveImageUpdateSubscriptions();
} }
@ -250,7 +247,7 @@ namespace LibationWinForms
if (editTagsForm.ShowDialog() != DialogResult.OK) if (editTagsForm.ShowDialog() != DialogResult.OK)
return; return;
var qtyChanges = context.UpdateTags(liveGridEntry.GetBook(), editTagsForm.NewTags); var qtyChanges = LibraryCommands.UpdateTags(liveGridEntry.GetBook(), editTagsForm.NewTags);
if (qtyChanges == 0) if (qtyChanges == 0)
return; return;
@ -337,7 +334,7 @@ namespace LibationWinForms
// //
// transform into sorted GridEntry.s BEFORE binding // transform into sorted GridEntry.s BEFORE binding
// //
context = DbContexts.GetContext(); using var context = DbContexts.GetContext();
var lib = context.GetLibrary_Flat_NoTracking(); var lib = context.GetLibrary_Flat_NoTracking();
// if no data. hide all columns. return // if no data. hide all columns. return