Added beta-specific logging
This commit is contained in:
parent
1375da2065
commit
6c9074169a
@ -51,77 +51,81 @@ namespace DtoImporterService
|
|||||||
var book = context.Books.Local.SingleOrDefault(p => p.AudibleProductId == item.ProductId);
|
var book = context.Books.Local.SingleOrDefault(p => p.AudibleProductId == item.ProductId);
|
||||||
if (book is null)
|
if (book is null)
|
||||||
{
|
{
|
||||||
// nested logic is required so order of names is retained. else, contributors may appear in the order they were inserted into the db
|
book = createNewBook(item, context);
|
||||||
var authors = item
|
|
||||||
.Authors
|
|
||||||
.Select(a => context.Contributors.Local.Single(c => a.Name == c.Name))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// if no narrators listed, author is the narrator
|
|
||||||
if (item.Narrators is null || !item.Narrators.Any())
|
|
||||||
item.Narrators = item.Authors;
|
|
||||||
// nested logic is required so order of names is retained. else, contributors may appear in the order they were inserted into the db
|
|
||||||
var narrators = item
|
|
||||||
.Narrators
|
|
||||||
.Select(n => context.Contributors.Local.Single(c => n.Name == c.Name))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
book = context.Books.Add(new Book(
|
|
||||||
new AudibleProductId(item.ProductId),
|
|
||||||
item.Title,
|
|
||||||
item.Description,
|
|
||||||
item.LengthInMinutes,
|
|
||||||
authors,
|
|
||||||
narrators)
|
|
||||||
).Entity;
|
|
||||||
|
|
||||||
var publisherName = item.Publisher;
|
|
||||||
if (!string.IsNullOrWhiteSpace(publisherName))
|
|
||||||
{
|
|
||||||
var publisher = context.Contributors.Local.Single(c => publisherName == c.Name);
|
|
||||||
book.ReplacePublisher(publisher);
|
|
||||||
}
|
|
||||||
|
|
||||||
qtyNew++;
|
qtyNew++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set/update book-specific info which may have changed
|
updateBook(item, book, context);
|
||||||
book.PictureId = item.PictureId;
|
|
||||||
book.UpdateProductRating(item.Product_OverallStars, item.Product_PerformanceStars, item.Product_StoryStars);
|
|
||||||
if (!string.IsNullOrWhiteSpace(item.SupplementUrl))
|
|
||||||
book.AddSupplementDownloadUrl(item.SupplementUrl);
|
|
||||||
|
|
||||||
// important to update user-specific info. this will have changed if user has rated/reviewed the book since last library import
|
|
||||||
book.UserDefinedItem.UpdateRating(item.MyUserRating_Overall, item.MyUserRating_Performance, item.MyUserRating_Story);
|
|
||||||
|
|
||||||
//
|
|
||||||
// this was round 1 when it was a 2 step process
|
|
||||||
//
|
|
||||||
//// update series even for existing books. these are occasionally updated
|
|
||||||
//var seriesIds = item.Series.Select(kvp => kvp.SeriesId).ToList();
|
|
||||||
//var allSeries = context.Series.Local.Where(c => seriesIds.Contains(c.AudibleSeriesId)).ToList();
|
|
||||||
//foreach (var series in allSeries)
|
|
||||||
// book.UpsertSeries(series);
|
|
||||||
|
|
||||||
// these will upsert over library-scraped series, but will not leave orphans
|
|
||||||
if (item.Series != null)
|
|
||||||
{
|
|
||||||
foreach (var seriesEntry in item.Series)
|
|
||||||
{
|
|
||||||
var series = context.Series.Local.Single(s => seriesEntry.SeriesId == s.AudibleSeriesId);
|
|
||||||
book.UpsertSeries(series, seriesEntry.Index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// categories are laid out for a breadcrumb. category is 1st, subcategory is 2nd
|
|
||||||
var category = context.Categories.Local.SingleOrDefault(c => c.AudibleCategoryId == item.Categories.LastOrDefault().CategoryId);
|
|
||||||
if (category != null)
|
|
||||||
book.UpdateCategory(category, context);
|
|
||||||
|
|
||||||
book.UpdateBookDetails(item.IsAbridged, item.DatePublished);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return qtyNew;
|
return qtyNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Book createNewBook(Item item, LibationContext context)
|
||||||
|
{
|
||||||
|
// nested logic is required so order of names is retained. else, contributors may appear in the order they were inserted into the db
|
||||||
|
var authors = item
|
||||||
|
.Authors
|
||||||
|
.Select(a => context.Contributors.Local.Single(c => a.Name == c.Name))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// if no narrators listed, author is the narrator
|
||||||
|
if (item.Narrators is null || !item.Narrators.Any())
|
||||||
|
item.Narrators = item.Authors;
|
||||||
|
// nested logic is required so order of names is retained. else, contributors may appear in the order they were inserted into the db
|
||||||
|
var narrators = item
|
||||||
|
.Narrators
|
||||||
|
.Select(n => context.Contributors.Local.Single(c => n.Name == c.Name))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var book = context.Books.Add(new Book(
|
||||||
|
new AudibleProductId(item.ProductId),
|
||||||
|
item.Title,
|
||||||
|
item.Description,
|
||||||
|
item.LengthInMinutes,
|
||||||
|
authors,
|
||||||
|
narrators)
|
||||||
|
).Entity;
|
||||||
|
|
||||||
|
var publisherName = item.Publisher;
|
||||||
|
if (!string.IsNullOrWhiteSpace(publisherName))
|
||||||
|
{
|
||||||
|
var publisher = context.Contributors.Local.Single(c => publisherName == c.Name);
|
||||||
|
book.ReplacePublisher(publisher);
|
||||||
|
}
|
||||||
|
|
||||||
|
// categories are laid out for a breadcrumb. category is 1st, subcategory is 2nd
|
||||||
|
var category = context.Categories.Local.SingleOrDefault(c => c.AudibleCategoryId == item.Categories.LastOrDefault().CategoryId);
|
||||||
|
if (category != null)
|
||||||
|
book.UpdateCategory(category, context);
|
||||||
|
|
||||||
|
book.UpdateBookDetails(item.IsAbridged, item.DatePublished);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(item.SupplementUrl))
|
||||||
|
book.AddSupplementDownloadUrl(item.SupplementUrl);
|
||||||
|
|
||||||
|
return book;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateBook(Item item, Book book, LibationContext context)
|
||||||
|
{
|
||||||
|
// set/update book-specific info which may have changed
|
||||||
|
book.PictureId = item.PictureId;
|
||||||
|
book.UpdateProductRating(item.Product_OverallStars, item.Product_PerformanceStars, item.Product_StoryStars);
|
||||||
|
|
||||||
|
// important to update user-specific info. this will have changed if user has rated/reviewed the book since last library import
|
||||||
|
book.UserDefinedItem.UpdateRating(item.MyUserRating_Overall, item.MyUserRating_Performance, item.MyUserRating_Story);
|
||||||
|
|
||||||
|
// update series even for existing books. these are occasionally updated
|
||||||
|
// these will upsert over library-scraped series, but will not leave orphans
|
||||||
|
if (item.Series != null)
|
||||||
|
{
|
||||||
|
foreach (var seriesEntry in item.Series)
|
||||||
|
{
|
||||||
|
var series = context.Series.Local.Single(s => seriesEntry.SeriesId == s.AudibleSeriesId);
|
||||||
|
book.UpsertSeries(series, seriesEntry.Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,10 +19,10 @@ namespace DtoImporterService
|
|||||||
var publishers = items.GetPublishersDistinct().ToList();
|
var publishers = items.GetPublishersDistinct().ToList();
|
||||||
|
|
||||||
// load db existing => .Local
|
// load db existing => .Local
|
||||||
var allNames = authors
|
var allNames = publishers
|
||||||
.Select(a => a.Name)
|
.Union(authors.Select(n => n.Name))
|
||||||
.Union(narrators.Select(n => n.Name))
|
.Union(narrators.Select(n => n.Name))
|
||||||
.Union(publishers)
|
.Where(name => !string.IsNullOrWhiteSpace(name))
|
||||||
.ToList();
|
.ToList();
|
||||||
loadLocal_contributors(allNames, context);
|
loadLocal_contributors(allNames, context);
|
||||||
|
|
||||||
@ -36,9 +36,6 @@ namespace DtoImporterService
|
|||||||
|
|
||||||
private void loadLocal_contributors(List<string> contributorNames, LibationContext context)
|
private void loadLocal_contributors(List<string> contributorNames, LibationContext context)
|
||||||
{
|
{
|
||||||
contributorNames.Remove(null);
|
|
||||||
contributorNames.Remove("");
|
|
||||||
|
|
||||||
//// BAD: very inefficient
|
//// BAD: very inefficient
|
||||||
// var x = context.Contributors.Local.Where(c => !contribNames.Contains(c.Name));
|
// var x = context.Contributors.Local.Where(c => !contribNames.Contains(c.Name));
|
||||||
|
|
||||||
|
|||||||
@ -20,12 +20,28 @@ namespace DtoImporterService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var exceptions = Validate(param);
|
try
|
||||||
if (exceptions != null && exceptions.Any())
|
{
|
||||||
throw new AggregateException($"Device Jobs Service configuration validation failed", exceptions);
|
var exceptions = Validate(param);
|
||||||
|
if (exceptions != null && exceptions.Any())
|
||||||
|
throw new AggregateException($"Importer validation failed", exceptions);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Error(ex, "Import error: validation");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
var result = func(param, context);
|
try
|
||||||
return result;
|
{
|
||||||
|
var result = func(param, context);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Error(ex, "Import error: post-validation importing");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
IEnumerable<Exception> Validate(T param);
|
IEnumerable<Exception> Validate(T param);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,17 +17,17 @@ namespace DtoImporterService
|
|||||||
var series = items.GetSeriesDistinct().ToList();
|
var series = items.GetSeriesDistinct().ToList();
|
||||||
|
|
||||||
// load db existing => .Local
|
// load db existing => .Local
|
||||||
var seriesIds = series.Select(s => s.SeriesId).ToList();
|
loadLocal_series(series, context);
|
||||||
loadLocal_series(seriesIds, context);
|
|
||||||
|
|
||||||
// upsert
|
// upsert
|
||||||
var qtyNew = upsertSeries(series, context);
|
var qtyNew = upsertSeries(series, context);
|
||||||
return qtyNew;
|
return qtyNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadLocal_series(List<string> seriesIds, LibationContext context)
|
private void loadLocal_series(List<AudibleApiDTOs.Series> series, LibationContext context)
|
||||||
{
|
{
|
||||||
var localIds = context.Series.Local.Select(s => s.AudibleSeriesId);
|
var seriesIds = series.Select(s => s.SeriesId).ToList();
|
||||||
|
var localIds = context.Series.Local.Select(s => s.AudibleSeriesId).ToList();
|
||||||
var remainingSeriesIds = seriesIds
|
var remainingSeriesIds = seriesIds
|
||||||
.Distinct()
|
.Distinct()
|
||||||
.Except(localIds)
|
.Except(localIds)
|
||||||
|
|||||||
@ -28,7 +28,7 @@ namespace InternalUtilities
|
|||||||
|
|
||||||
private async Task<List<Item>> getItemsAsync(ILoginCallback callback)
|
private async Task<List<Item>> getItemsAsync(ILoginCallback callback)
|
||||||
{
|
{
|
||||||
var api = await EzApiCreator.GetApiAsync(AudibleApiStorage.IdentityTokensFile, callback, Configuration.Instance.LocaleCountryCode);
|
var api = await getApiAsync(callback);
|
||||||
var items = await AudibleApiExtensions.GetAllLibraryItemsAsync(api);
|
var items = await AudibleApiExtensions.GetAllLibraryItemsAsync(api);
|
||||||
|
|
||||||
// remove episode parents
|
// remove episode parents
|
||||||
@ -62,6 +62,20 @@ namespace InternalUtilities
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<Api> getApiAsync(ILoginCallback callback)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await EzApiCreator.GetApiAsync(AudibleApiStorage.IdentityTokensFile, callback, Configuration.Instance.LocaleCountryCode);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Error(ex, "Error getting Audible API");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static List<IValidator> getValidators()
|
private static List<IValidator> getValidators()
|
||||||
{
|
{
|
||||||
var type = typeof(IValidator);
|
var type = typeof(IValidator);
|
||||||
|
|||||||
@ -27,8 +27,19 @@ namespace InternalUtilities
|
|||||||
ResponseGroups = LibraryOptions.ResponseGroupOptions.ALL_OPTIONS
|
ResponseGroups = LibraryOptions.ResponseGroupOptions.ALL_OPTIONS
|
||||||
});
|
});
|
||||||
|
|
||||||
// important! use this convert method
|
string pageStr = null;
|
||||||
var libResult = LibraryDtoV10.FromJson(page.ToString());
|
LibraryDtoV10 libResult;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pageStr = page.ToString();
|
||||||
|
// important! use this convert method
|
||||||
|
libResult = LibraryDtoV10.FromJson(pageStr);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Serilog.Log.Logger.Error(ex, "Error converting library for importing use. Full library:\r\n" + pageStr);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
if (!libResult.Items.Any())
|
if (!libResult.Items.Any())
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System.Windows.Forms;
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
using ApplicationServices;
|
using ApplicationServices;
|
||||||
|
|
||||||
namespace LibationWinForm
|
namespace LibationWinForm
|
||||||
@ -20,9 +21,11 @@ namespace LibationWinForm
|
|||||||
{
|
{
|
||||||
(TotalBooksProcessed, NewBooksAdded) = await LibraryCommands.IndexLibraryAsync(new Login.WinformResponder());
|
(TotalBooksProcessed, NewBooksAdded) = await LibraryCommands.IndexLibraryAsync(new Login.WinformResponder());
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.Show("Error importing library. Please try again. If this happens after 2 or 3 tries, contact administrator", "Error importing library", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
var msg = "Error importing library. Please try again. If this happens after 2 or 3 tries, contact administrator";
|
||||||
|
Serilog.Log.Logger.Error(ex, msg);
|
||||||
|
MessageBox.Show(msg, "Error importing library", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Close();
|
this.Close();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
namespace LibationWinForm
|
namespace LibationWinForm
|
||||||
{
|
{
|
||||||
@ -14,6 +15,8 @@ namespace LibationWinForm
|
|||||||
if (!createSettings())
|
if (!createSettings())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
Application.Run(new Form1());
|
Application.Run(new Form1());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +32,7 @@ Please fill in a few settings on the following page. You can also change these s
|
|||||||
After you make your selections, get started by importing your library.
|
After you make your selections, get started by importing your library.
|
||||||
Go to Import > Scan Library
|
Go to Import > Scan Library
|
||||||
".Trim();
|
".Trim();
|
||||||
MessageBox.Show(welcomeText, "Welcom to Libation", MessageBoxButtons.OK);
|
MessageBox.Show(welcomeText, "Welcome to Libation", MessageBoxButtons.OK);
|
||||||
var dialogResult = new SettingsDialog().ShowDialog();
|
var dialogResult = new SettingsDialog().ShowDialog();
|
||||||
if (dialogResult != DialogResult.OK)
|
if (dialogResult != DialogResult.OK)
|
||||||
{
|
{
|
||||||
@ -39,5 +42,14 @@ Go to Import > Scan Library
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void init()
|
||||||
|
{
|
||||||
|
var logPath = System.IO.Path.Combine(FileManager.Configuration.Instance.LibationFiles, "Log.log");
|
||||||
|
Log.Logger = new LoggerConfiguration()
|
||||||
|
.MinimumLevel.Debug()
|
||||||
|
.WriteTo.File(logPath, rollingInterval: RollingInterval.Month)
|
||||||
|
.CreateLogger();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
-- begin VERSIONING ---------------------------------------------------------------------------------------------------------------------
|
-- begin VERSIONING ---------------------------------------------------------------------------------------------------------------------
|
||||||
https://github.com/rmcrackan/Libation/releases
|
https://github.com/rmcrackan/Libation/releases
|
||||||
|
|
||||||
|
v3.1-beta.3 : fixed known performance issue: Full-screen grid is slow to respond loading when books aren't liberated
|
||||||
v3.1-beta.2 : fixed known performance issue: Tag add/edit
|
v3.1-beta.2 : fixed known performance issue: Tag add/edit
|
||||||
v3.1-beta.1 : RELEASE TO BETA
|
v3.1-beta.1 : RELEASE TO BETA
|
||||||
v3.0.3 : Switch to SQLite. No longer relies on LocalDB, which must be installed separately
|
v3.0.3 : Switch to SQLite. No longer relies on LocalDB, which must be installed separately
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user