diff --git a/AppScaffolding/AppScaffolding.csproj b/AppScaffolding/AppScaffolding.csproj index 1e712e8e..278c50b0 100644 --- a/AppScaffolding/AppScaffolding.csproj +++ b/AppScaffolding/AppScaffolding.csproj @@ -3,7 +3,7 @@ net5.0 - 5.7.5.1 + 6.0.0.1 diff --git a/ApplicationServices/LibraryCommands.cs b/ApplicationServices/LibraryCommands.cs index da35e4c3..5422f987 100644 --- a/ApplicationServices/LibraryCommands.cs +++ b/ApplicationServices/LibraryCommands.cs @@ -136,11 +136,11 @@ namespace ApplicationServices { var callback = loginCallbackFactoryFunc(account); - // get APIs in serial, esp b/c of logins - var api = await AudibleApiActions.GetApiAsync(callback, account); + // get APIs in serial b/c of logins + var apiExtended = await ApiExtended.CreateAsync(callback, account); // add scanAccountAsync as a TASK: do not await - tasks.Add(scanAccountAsync(api, account)); + tasks.Add(scanAccountAsync(apiExtended, account)); } // import library in parallel @@ -149,7 +149,7 @@ namespace ApplicationServices return importItems; } - private static async Task> scanAccountAsync(Api api, Account account) + private static async Task> scanAccountAsync(ApiExtended apiExtended, Account account) { ArgumentValidator.EnsureNotNull(account, nameof(account)); @@ -160,7 +160,7 @@ namespace ApplicationServices logTime($"pre scanAccountAsync {account.AccountName}"); - var dtoItems = await AudibleApiActions.GetLibraryValidatedAsync(api, LibraryResponseGroups); + var dtoItems = await apiExtended.GetLibraryValidatedAsync(LibraryResponseGroups); logTime($"post scanAccountAsync {account.AccountName} qty: {dtoItems.Count}"); diff --git a/FileLiberator/DownloadDecryptBook.cs b/FileLiberator/DownloadDecryptBook.cs index 9836d8f1..61c813f1 100644 --- a/FileLiberator/DownloadDecryptBook.cs +++ b/FileLiberator/DownloadDecryptBook.cs @@ -84,16 +84,16 @@ namespace FileLiberator { validate(libraryBook); - var api = await InternalUtilities.AudibleApiActions.GetApiAsync(libraryBook.Account, libraryBook.Book.Locale); + var apiExtended = await InternalUtilities.ApiExtended.CreateAsync(libraryBook.Account, libraryBook.Book.Locale); - var contentLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId); + var contentLic = await apiExtended.Api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId); var aaxcDecryptDlLic = new DownloadLicense ( contentLic?.ContentMetadata?.ContentUrl?.OfflineUrl, contentLic?.Voucher?.Key, contentLic?.Voucher?.Iv, - Resources.UserAgent + Resources.USER_AGENT ); if (Configuration.Instance.AllowLibationFixup) diff --git a/FileLiberator/DownloadPdf.cs b/FileLiberator/DownloadPdf.cs index e843dfa1..6b37278e 100644 --- a/FileLiberator/DownloadPdf.cs +++ b/FileLiberator/DownloadPdf.cs @@ -59,8 +59,8 @@ namespace FileLiberator private async Task downloadPdfAsync(LibraryBook libraryBook, string proposedDownloadFilePath) { - var api = await GetApiAsync(libraryBook); - var downloadUrl = await api.GetPdfDownloadLinkAsync(libraryBook.Book.AudibleProductId); + var apiExtended = await GetApiExtendedAsync(libraryBook); + var downloadUrl = await apiExtended.Api.GetPdfDownloadLinkAsync(libraryBook.Book.AudibleProductId); var client = new HttpClient(); var actualDownloadedFilePath = await PerformDownloadAsync( diff --git a/FileLiberator/DownloadableBase.cs b/FileLiberator/DownloadableBase.cs index 38b5a76e..84351627 100644 --- a/FileLiberator/DownloadableBase.cs +++ b/FileLiberator/DownloadableBase.cs @@ -40,8 +40,8 @@ namespace FileLiberator } } - protected static Task GetApiAsync(LibraryBook libraryBook) - => InternalUtilities.AudibleApiActions.GetApiAsync(libraryBook.Account, libraryBook.Book.Locale); + protected static Task GetApiExtendedAsync(LibraryBook libraryBook) + => InternalUtilities.ApiExtended.CreateAsync(libraryBook.Account, libraryBook.Book.Locale); protected async Task PerformDownloadAsync(string proposedDownloadFilePath, Func, Task> func) { diff --git a/InternalUtilities/AudibleApiActions.cs b/InternalUtilities/ApiExtended.cs similarity index 79% rename from InternalUtilities/AudibleApiActions.cs rename to InternalUtilities/ApiExtended.cs index cee74fee..5252e74f 100644 --- a/InternalUtilities/AudibleApiActions.cs +++ b/InternalUtilities/ApiExtended.cs @@ -10,36 +10,42 @@ using Polly.Retry; namespace InternalUtilities { - public static class AudibleApiActions + /// USE THIS from within Libation. It wraps the call with correct JSONPath + public class ApiExtended { - /// USE THIS from within Libation. It wraps the call with correct JSONPath - public static Task GetApiAsync(string username, string localeName, ILoginCallback loginCallback = null) + public Api Api { get; private set; } + + private ApiExtended(Api api) => Api = api; + + public static async Task CreateAsync(string username, string localeName) { Serilog.Log.Logger.Information("GetApiAsync. {@DebugInfo}", new { Username = username.ToMask(), LocaleName = localeName, }); - return EzApiCreator.GetApiAsync( - Localization.Get(localeName), - AudibleApiStorage.AccountsSettingsFile, - AudibleApiStorage.GetIdentityTokensJsonPath(username, localeName), - loginCallback); + + var api = await EzApiCreator.GetApiAsync( + Localization.Get(localeName), + AudibleApiStorage.AccountsSettingsFile, + AudibleApiStorage.GetIdentityTokensJsonPath(username, localeName)); + return new ApiExtended(api); } - /// USE THIS from within Libation. It wraps the call with correct JSONPath - public static Task GetApiAsync(ILoginCallback loginCallback, Account account) + public static async Task CreateAsync(ILoginCallback loginCallback, Account account) { Serilog.Log.Logger.Information("GetApiAsync. {@DebugInfo}", new { Account = account?.MaskedLogEntry ?? "[null]", LocaleName = account?.Locale?.Name }); - return EzApiCreator.GetApiAsync( + + var api = await EzApiCreator.GetApiAsync( account.Locale, AudibleApiStorage.AccountsSettingsFile, - account.GetIdentityTokensJsonPath(), - loginCallback); + loginCallback, + account.GetIdentityTokensJsonPath()); + return new ApiExtended(api); } private static AsyncRetryPolicy policy { get; } @@ -47,16 +53,16 @@ namespace InternalUtilities // 2 retries == 3 total .RetryAsync(2); - public static Task> GetLibraryValidatedAsync(Api api, LibraryOptions.ResponseGroupOptions responseGroups = LibraryOptions.ResponseGroupOptions.ALL_OPTIONS) + public Task> GetLibraryValidatedAsync(LibraryOptions.ResponseGroupOptions responseGroups = LibraryOptions.ResponseGroupOptions.ALL_OPTIONS) { // bug on audible's side. the 1st time after a long absence, a query to get library will return without titles or authors. a subsequent identical query will be successful. this is true whether or tokens are refreshed // worse, this 1st dummy call doesn't seem to help: // var page = await api.GetLibraryAsync(new AudibleApi.LibraryOptions { NumberOfResultPerPage = 1, PageNumber = 1, PurchasedAfter = DateTime.Now.AddYears(-20), ResponseGroups = AudibleApi.LibraryOptions.ResponseGroupOptions.ALL_OPTIONS }); // i don't want to incur the cost of making a full dummy call every time because it fails sometimes - return policy.ExecuteAsync(() => getItemsAsync(api, responseGroups)); + return policy.ExecuteAsync(() => getItemsAsync(responseGroups)); } - private static async Task> getItemsAsync(Api api, LibraryOptions.ResponseGroupOptions responseGroups) + private async Task> getItemsAsync(LibraryOptions.ResponseGroupOptions responseGroups) { var items = new List(); #if DEBUG @@ -68,12 +74,12 @@ namespace InternalUtilities //} #endif if (!items.Any()) - items = await api.GetAllLibraryItemsAsync(responseGroups); + items = await Api.GetAllLibraryItemsAsync(responseGroups); #if DEBUG //System.IO.File.WriteAllText("library.json", AudibleApi.Common.Converter.ToJson(items)); #endif - await manageEpisodesAsync(api, items); + await manageEpisodesAsync(items); var validators = new List(); validators.AddRange(getValidators()); @@ -88,7 +94,7 @@ namespace InternalUtilities } #region episodes and podcasts - private static async Task manageEpisodesAsync(Api api, List items) + private async Task manageEpisodesAsync(List items) { // add podcasts and episodes to list. If fail, don't let it de-rail the rest of the import try @@ -110,7 +116,7 @@ namespace InternalUtilities items.RemoveAll(i => i.IsEpisodes); // add children - var children = await getEpisodesAsync(api, parents); + var children = await getEpisodesAsync(parents); Serilog.Log.Logger.Information($"{children.Count} episodes of shows/podcasts found"); items.AddRange(children); } @@ -120,13 +126,13 @@ namespace InternalUtilities } } - private static async Task> getEpisodesAsync(Api api, List parents) + private async Task> getEpisodesAsync(List parents) { var results = new List(); foreach (var parent in parents) { - var children = await getEpisodeChildrenAsync(api, parent); + var children = await getEpisodeChildrenAsync(parent); foreach (var child in children) { @@ -159,7 +165,7 @@ namespace InternalUtilities return results; } - private static async Task> getEpisodeChildrenAsync(Api api, Item parent) + private async Task> getEpisodeChildrenAsync(Item parent) { var childrenIds = parent.Relationships .Where(r => r.RelationshipToProduct == RelationshipToProduct.Child && r.RelationshipType == RelationshipType.Episode) @@ -180,7 +186,7 @@ namespace InternalUtilities List childrenBatch; try { - childrenBatch = await api.GetCatalogProductsAsync(idBatch, CatalogOptions.ResponseGroupOptions.ALL_OPTIONS); + childrenBatch = await Api.GetCatalogProductsAsync(idBatch, CatalogOptions.ResponseGroupOptions.ALL_OPTIONS); #if DEBUG //var childrenBatchDebug = childrenBatch.Select(i => i.ToJson()).Aggregate((a, b) => $"{a}\r\n\r\n{b}"); //System.IO.File.WriteAllText($"children of {parent.Asin}.json", childrenBatchDebug); @@ -222,7 +228,7 @@ namespace InternalUtilities return results; } -#endregion + #endregion private static List getValidators() { diff --git a/InternalUtilities/InternalUtilities.csproj b/InternalUtilities/InternalUtilities.csproj index 4b0bbf44..eddf21f6 100644 --- a/InternalUtilities/InternalUtilities.csproj +++ b/InternalUtilities/InternalUtilities.csproj @@ -5,7 +5,7 @@ - + diff --git a/LibationWinForms/Dialogs/Login/WinformResponder.cs b/LibationWinForms/Dialogs/Login/WinformResponder.cs index cc73d713..28507f4d 100644 --- a/LibationWinForms/Dialogs/Login/WinformResponder.cs +++ b/LibationWinForms/Dialogs/Login/WinformResponder.cs @@ -1,8 +1,7 @@ -using AudibleApi; +using System; +using AudibleApi; using InternalUtilities; using LibationWinForms.Dialogs.Login; -using System; -using System.Linq; namespace LibationWinForms.Login { diff --git a/LibationWinForms/Program.cs b/LibationWinForms/Program.cs index 68c5fd7f..66ee6630 100644 --- a/LibationWinForms/Program.cs +++ b/LibationWinForms/Program.cs @@ -183,7 +183,8 @@ namespace LibationWinForms authorize.DeregisterAsync(identity.ExistingAccessToken, identity.Cookies.ToKeyValuePair()).GetAwaiter().GetResult(); identity.Invalidate(); - var api = AudibleApiActions.GetApiAsync(new Login.WinformResponder(account), account).GetAwaiter().GetResult(); + // re-registers device + ApiExtended.CreateAsync(new Login.WinformResponder(account), account).GetAwaiter().GetResult(); } catch {