From 368e6952148c5cc81c408e3e95facc471ee1fde3 Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Tue, 2 Dec 2025 12:20:18 -0700 Subject: [PATCH] Allow users to shoose whether Libation imports Audible Plus titles. --- Source/ApplicationServices/LibraryCommands.cs | 2 +- Source/AudibleUtilities/ApiExtended.cs | 21 +++++---- .../Controls/Settings/Import.axaml | 4 ++ .../ViewModels/Settings/ImportSettingsVM.cs | 4 ++ .../Configuration.PersistentSettings.cs | 3 ++ .../Dialogs/SettingsDialog.Designer.cs | 43 ++++++++++++------- .../Dialogs/SettingsDialog.ImportLibrary.cs | 3 ++ 7 files changed, 56 insertions(+), 24 deletions(-) diff --git a/Source/ApplicationServices/LibraryCommands.cs b/Source/ApplicationServices/LibraryCommands.cs index 59d959b6..aff6c629 100644 --- a/Source/ApplicationServices/LibraryCommands.cs +++ b/Source/ApplicationServices/LibraryCommands.cs @@ -299,7 +299,7 @@ namespace ApplicationServices try { - var dtoItems = await apiExtended.GetLibraryValidatedAsync(libraryOptions, Configuration.Instance.ImportEpisodes); + var dtoItems = await apiExtended.GetLibraryValidatedAsync(libraryOptions); logTime($"post scanAccountAsync {account.AccountName} qty: {dtoItems.Count}"); diff --git a/Source/AudibleUtilities/ApiExtended.cs b/Source/AudibleUtilities/ApiExtended.cs index 50f036a9..7e3d4df9 100644 --- a/Source/AudibleUtilities/ApiExtended.cs +++ b/Source/AudibleUtilities/ApiExtended.cs @@ -10,6 +10,7 @@ using Dinah.Core; using Polly; using Polly.Retry; using System.Threading; +using LibationFileManager; #nullable enable namespace AudibleUtilities @@ -72,16 +73,16 @@ namespace AudibleUtilities // 2 retries == 3 total .RetryAsync(2); - public Task> GetLibraryValidatedAsync(LibraryOptions libraryOptions, bool importEpisodes = true) + public Task> GetLibraryValidatedAsync(LibraryOptions libraryOptions) { // 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 not 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(libraryOptions, importEpisodes)); + return policy.ExecuteAsync(() => getItemsAsync(libraryOptions)); } - private async Task> getItemsAsync(LibraryOptions libraryOptions, bool importEpisodes) + private async Task> getItemsAsync(LibraryOptions libraryOptions) { Serilog.Log.Logger.Debug("Beginning library scan."); @@ -95,12 +96,12 @@ namespace AudibleUtilities //Scan the library for all added books. //Get relationship asins from episode-type items and write them to episodeChannel where they will be batched and queried. - await foreach (var item in Api.GetLibraryItemsPagesAsync(libraryOptions, BatchSize, semaphore)) + await foreach (var itemsBatch in Api.GetLibraryItemsPagesAsync(libraryOptions, BatchSize, semaphore)) { - if (importEpisodes) + if (Configuration.Instance.ImportEpisodes) { - var episodes = item.Where(i => i.IsEpisodes).ToList(); - var series = item.Where(i => i.IsSeriesParent).ToList(); + var episodes = itemsBatch.Where(i => i.IsEpisodes).ToList(); + var series = itemsBatch.Where(i => i.IsSeriesParent).ToList(); var parentAsins = episodes .SelectMany(i => i.Relationships) @@ -119,7 +120,11 @@ namespace AudibleUtilities items.AddRange(series); } - items.AddRange(item.Where(i => !i.IsSeriesParent && !i.IsEpisodes)); + var booksInBatch + = itemsBatch + .Where(i => !i.IsSeriesParent && !i.IsEpisodes) + .Where(i => i.IsAyce is not true || Configuration.Instance.ImportPlusTitles); + items.AddRange(booksInBatch); } sw.Stop(); diff --git a/Source/LibationAvalonia/Controls/Settings/Import.axaml b/Source/LibationAvalonia/Controls/Settings/Import.axaml index a78daaee..affb6cda 100644 --- a/Source/LibationAvalonia/Controls/Settings/Import.axaml +++ b/Source/LibationAvalonia/Controls/Settings/Import.axaml @@ -30,6 +30,10 @@ + + + + diff --git a/Source/LibationAvalonia/ViewModels/Settings/ImportSettingsVM.cs b/Source/LibationAvalonia/ViewModels/Settings/ImportSettingsVM.cs index 0df3dc6a..f9417ca9 100644 --- a/Source/LibationAvalonia/ViewModels/Settings/ImportSettingsVM.cs +++ b/Source/LibationAvalonia/ViewModels/Settings/ImportSettingsVM.cs @@ -10,6 +10,7 @@ namespace LibationAvalonia.ViewModels.Settings AutoScan = config.AutoScan; ShowImportedStats = config.ShowImportedStats; ImportEpisodes = config.ImportEpisodes; + ImportPlusTitles = config.ImportPlusTitles; DownloadEpisodes = config.DownloadEpisodes; AutoDownloadEpisodes = config.AutoDownloadEpisodes; } @@ -19,6 +20,7 @@ namespace LibationAvalonia.ViewModels.Settings config.AutoScan = AutoScan; config.ShowImportedStats = ShowImportedStats; config.ImportEpisodes = ImportEpisodes; + config.ImportPlusTitles = ImportPlusTitles; config.DownloadEpisodes = DownloadEpisodes; config.AutoDownloadEpisodes = AutoDownloadEpisodes; } @@ -26,12 +28,14 @@ namespace LibationAvalonia.ViewModels.Settings public string AutoScanText { get; } = Configuration.GetDescription(nameof(Configuration.AutoScan)); public string ShowImportedStatsText { get; } = Configuration.GetDescription(nameof(Configuration.ShowImportedStats)); public string ImportEpisodesText { get; } = Configuration.GetDescription(nameof(Configuration.ImportEpisodes)); + public string ImportPlusTitlesText { get; } = Configuration.GetDescription(nameof(Configuration.ImportPlusTitles)); public string DownloadEpisodesText { get; } = Configuration.GetDescription(nameof(Configuration.DownloadEpisodes)); public string AutoDownloadEpisodesText { get; } = Configuration.GetDescription(nameof(Configuration.AutoDownloadEpisodes)); public bool AutoScan { get; set; } public bool ShowImportedStats { get; set; } public bool ImportEpisodes { get; set; } + public bool ImportPlusTitles { get; set; } public bool DownloadEpisodes { get; set; } public bool AutoDownloadEpisodes { get; set; } } diff --git a/Source/LibationFileManager/Configuration.PersistentSettings.cs b/Source/LibationFileManager/Configuration.PersistentSettings.cs index 30c8dbc2..45aaa63a 100644 --- a/Source/LibationFileManager/Configuration.PersistentSettings.cs +++ b/Source/LibationFileManager/Configuration.PersistentSettings.cs @@ -330,6 +330,9 @@ namespace LibationFileManager [Description("Import episodes? (eg: podcasts) When unchecked, episodes will not be imported into Libation.")] public bool ImportEpisodes { get => GetNonString(defaultValue: true); set => SetNonString(value); } + [Description("Import Audible Plus books (books you do not own)? When unchecked, Audible Plus books will not be imported into Libation.")] + public bool ImportPlusTitles { get => GetNonString(defaultValue: true); set => SetNonString(value); } + [Description("Download episodes? (eg: podcasts). When unchecked, episodes already in Libation will not be downloaded.")] public bool DownloadEpisodes { get => GetNonString(defaultValue: true); set => SetNonString(value); } diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs index d00ceaef..069ce7c9 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.Designer.cs @@ -49,6 +49,7 @@ loggingLevelCb = new System.Windows.Forms.ComboBox(); tabControl = new System.Windows.Forms.TabControl(); tab1ImportantSettings = new System.Windows.Forms.TabPage(); + themeLbl = new System.Windows.Forms.Label(); themeCb = new System.Windows.Forms.ComboBox(); label22 = new System.Windows.Forms.Label(); groupBox1 = new System.Windows.Forms.GroupBox(); @@ -66,6 +67,7 @@ overwriteExistingCbox = new System.Windows.Forms.CheckBox(); saveEpisodesToSeriesFolderCbox = new System.Windows.Forms.CheckBox(); tab2ImportLibrary = new System.Windows.Forms.TabPage(); + importPlusTitlesCb = new System.Windows.Forms.CheckBox(); autoDownloadEpisodesCb = new System.Windows.Forms.CheckBox(); autoScanCb = new System.Windows.Forms.CheckBox(); showImportedStatsCb = new System.Windows.Forms.CheckBox(); @@ -139,7 +141,6 @@ retainAaxFileCbox = new System.Windows.Forms.CheckBox(); downloadCoverArtCbox = new System.Windows.Forms.CheckBox(); createCueSheetCbox = new System.Windows.Forms.CheckBox(); - themeLbl = new System.Windows.Forms.Label(); badBookGb.SuspendLayout(); tabControl.SuspendLayout(); tab1ImportantSettings.SuspendLayout(); @@ -220,10 +221,10 @@ // downloadEpisodesCb // downloadEpisodesCb.AutoSize = true; - downloadEpisodesCb.Location = new System.Drawing.Point(6, 81); + downloadEpisodesCb.Location = new System.Drawing.Point(6, 106); downloadEpisodesCb.Name = "downloadEpisodesCb"; downloadEpisodesCb.Size = new System.Drawing.Size(163, 19); - downloadEpisodesCb.TabIndex = 4; + downloadEpisodesCb.TabIndex = 5; downloadEpisodesCb.Text = "[download episodes desc]"; downloadEpisodesCb.UseVisualStyleBackColor = true; // @@ -404,10 +405,19 @@ tab1ImportantSettings.TabIndex = 0; tab1ImportantSettings.Text = "Important settings"; // + // themeLbl + // + themeLbl.AutoSize = true; + themeLbl.Location = new System.Drawing.Point(190, 393); + themeLbl.Name = "themeLbl"; + themeLbl.Size = new System.Drawing.Size(296, 15); + themeLbl.TabIndex = 12; + themeLbl.Text = "You must restart Libation for this change to take effect."; + // // themeCb // - themeCb.FormattingEnabled = true; themeCb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + themeCb.FormattingEnabled = true; themeCb.Location = new System.Drawing.Point(63, 390); themeCb.Name = "themeCb"; themeCb.Size = new System.Drawing.Size(121, 23); @@ -579,6 +589,7 @@ // tab2ImportLibrary.AutoScroll = true; tab2ImportLibrary.BackColor = System.Drawing.SystemColors.Window; + tab2ImportLibrary.Controls.Add(importPlusTitlesCb); tab2ImportLibrary.Controls.Add(autoDownloadEpisodesCb); tab2ImportLibrary.Controls.Add(autoScanCb); tab2ImportLibrary.Controls.Add(showImportedStatsCb); @@ -591,13 +602,23 @@ tab2ImportLibrary.TabIndex = 1; tab2ImportLibrary.Text = "Import library"; // + // importPlusTitlesCb + // + importPlusTitlesCb.AutoSize = true; + importPlusTitlesCb.Location = new System.Drawing.Point(6, 81); + importPlusTitlesCb.Name = "importPlusTitlesCb"; + importPlusTitlesCb.Size = new System.Drawing.Size(199, 19); + importPlusTitlesCb.TabIndex = 4; + importPlusTitlesCb.Text = "[import audible plus books desc]"; + importPlusTitlesCb.UseVisualStyleBackColor = true; + // // autoDownloadEpisodesCb // autoDownloadEpisodesCb.AutoSize = true; - autoDownloadEpisodesCb.Location = new System.Drawing.Point(6, 106); + autoDownloadEpisodesCb.Location = new System.Drawing.Point(6, 131); autoDownloadEpisodesCb.Name = "autoDownloadEpisodesCb"; autoDownloadEpisodesCb.Size = new System.Drawing.Size(190, 19); - autoDownloadEpisodesCb.TabIndex = 5; + autoDownloadEpisodesCb.TabIndex = 6; autoDownloadEpisodesCb.Text = "[auto download episodes desc]"; autoDownloadEpisodesCb.UseVisualStyleBackColor = true; // @@ -1438,15 +1459,6 @@ createCueSheetCbox.UseVisualStyleBackColor = true; createCueSheetCbox.CheckedChanged += allowLibationFixupCbox_CheckedChanged; // - // themeLbl - // - themeLbl.AutoSize = true; - themeLbl.Location = new System.Drawing.Point(190, 393); - themeLbl.Name = "themeLbl"; - themeLbl.Size = new System.Drawing.Size(296, 15); - themeLbl.TabIndex = 12; - themeLbl.Text = "You must restart Libation for this change to take effect."; - // // SettingsDialog // AcceptButton = saveBtn; @@ -1615,5 +1627,6 @@ private System.Windows.Forms.Label label22; private System.Windows.Forms.ComboBox themeCb; private System.Windows.Forms.Label themeLbl; + private System.Windows.Forms.CheckBox importPlusTitlesCb; } } \ No newline at end of file diff --git a/Source/LibationWinForms/Dialogs/SettingsDialog.ImportLibrary.cs b/Source/LibationWinForms/Dialogs/SettingsDialog.ImportLibrary.cs index c381b7b8..8376d890 100644 --- a/Source/LibationWinForms/Dialogs/SettingsDialog.ImportLibrary.cs +++ b/Source/LibationWinForms/Dialogs/SettingsDialog.ImportLibrary.cs @@ -12,12 +12,14 @@ namespace LibationWinForms.Dialogs this.autoScanCb.Text = desc(nameof(config.AutoScan)); this.showImportedStatsCb.Text = desc(nameof(config.ShowImportedStats)); this.importEpisodesCb.Text = desc(nameof(config.ImportEpisodes)); + this.importPlusTitlesCb.Text = desc(nameof(config.ImportPlusTitles)); this.downloadEpisodesCb.Text = desc(nameof(config.DownloadEpisodes)); this.autoDownloadEpisodesCb.Text = desc(nameof(config.AutoDownloadEpisodes)); autoScanCb.Checked = config.AutoScan; showImportedStatsCb.Checked = config.ShowImportedStats; importEpisodesCb.Checked = config.ImportEpisodes; + importPlusTitlesCb.Checked = config.ImportPlusTitles; downloadEpisodesCb.Checked = config.DownloadEpisodes; autoDownloadEpisodesCb.Checked = config.AutoDownloadEpisodes; } @@ -26,6 +28,7 @@ namespace LibationWinForms.Dialogs config.AutoScan = autoScanCb.Checked; config.ShowImportedStats = showImportedStatsCb.Checked; config.ImportEpisodes = importEpisodesCb.Checked; + config.ImportPlusTitles = importPlusTitlesCb.Checked; config.DownloadEpisodes = downloadEpisodesCb.Checked; config.AutoDownloadEpisodes = autoDownloadEpisodesCb.Checked; }