Improve detection and logging of download capabilities

- Check if the Api supports widevine before trying to download
- Additional logging
This commit is contained in:
Michael Bucari-Tovo
2025-11-04 14:32:28 -07:00
parent 017902ab52
commit 7507044b82
5 changed files with 51 additions and 12 deletions

View File

@@ -6,6 +6,7 @@ using AudibleApi.Authorization;
using Dinah.Core;
using Newtonsoft.Json;
#nullable enable
namespace AudibleUtilities
{
// 'AccountsSettings' is intentionally NOT IEnumerable<> so that properties can be added/extended
@@ -14,8 +15,8 @@ namespace AudibleUtilities
// JSON : Array (properties on the collection will not be serialized)
public class AccountsSettings : IUpdatable
{
public event EventHandler Updated;
private void update(object sender = null, EventArgs e = null)
public event EventHandler? Updated;
private void update(object? sender = null, EventArgs? e = null)
{
foreach (var account in Accounts)
validate(account);
@@ -48,9 +49,9 @@ namespace AudibleUtilities
}
}
private string _cdm;
private string? _cdm;
[JsonProperty]
public string Cdm
public string? Cdm
{
get => _cdm;
set
@@ -68,7 +69,7 @@ namespace AudibleUtilities
#endregion
#region de/serialize
public static AccountsSettings FromJson(string json)
public static AccountsSettings? FromJson(string json)
=> JsonConvert.DeserializeObject<AccountsSettings>(json, Identity.GetJsonSerializerSettings());
public string ToJson(Formatting formatting = Formatting.Indented)
@@ -107,7 +108,7 @@ namespace AudibleUtilities
account.Updated += update;
}
public Account GetAccount(string accountId, string locale)
public Account? GetAccount(string accountId, string? locale)
{
if (locale is null)
return null;

View File

@@ -3,6 +3,7 @@ using AudibleApi;
using AudibleApi.Common;
using AudibleUtilities.Widevine;
using DataLayer;
using Dinah.Core;
using LibationFileManager;
using NAudio.Lame;
using System;
@@ -24,6 +25,16 @@ public partial class DownloadOptions
public static async Task<DownloadOptions> InitiateDownloadAsync(Api api, Configuration config, LibraryBook libraryBook, CancellationToken token)
{
var license = await ChooseContent(api, libraryBook, config, token);
Serilog.Log.Logger.Debug("Content License {@License}", new
{
license.DrmType,
license.ContentMetadata.ContentReference.Codec,
license.ContentMetadata.ContentReference.Marketplace,
license.ContentMetadata.ContentReference.ContentSizeInBytes,
license.ContentMetadata.ContentReference.Version,
license.ContentMetadata.ContentReference.FileVersion
});
token.ThrowIfCancellationRequested();
//Some audiobooks will have incorrect chapters in the metadata returned from the license request,
@@ -56,10 +67,28 @@ public partial class DownloadOptions
private static async Task<LicenseInfo> ChooseContent(Api api, LibraryBook libraryBook, Configuration config, CancellationToken token)
{
Serilog.Log.Logger.Debug("Download Settings {@Settings}", new
{
config.FileDownloadQuality,
config.UseWidevine,
config.Request_xHE_AAC,
config.RequestSpatial,
config.SpatialAudioCodec
});
var dlQuality = config.FileDownloadQuality == Configuration.DownloadQuality.Normal ? DownloadQuality.Normal : DownloadQuality.High;
if (!config.UseWidevine || await Cdm.GetCdmAsync() is not Cdm cdm)
bool canUseWidevine = api.SupportsWidevine();
if (!config.UseWidevine || !canUseWidevine || await Cdm.GetCdmAsync() is not Cdm cdm)
{
if (config.UseWidevine)
{
if (canUseWidevine)
Serilog.Log.Logger.Information("Unable to get a Widevine CDM. Falling back to ADRM.");
else
Serilog.Log.Logger.Information("Account {@account} is not registered as an android device, so content will not be downloaded with Widevine DRM. Remove and re-add the account in Libation to fix.", libraryBook.Account.ToMask());
}
token.ThrowIfCancellationRequested();
var license = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId, dlQuality);
return new LicenseInfo(license);

View File

@@ -7,6 +7,7 @@ using DataLayer;
using Dinah.Core;
using LibationFileManager;
using LibationFileManager.Templates;
using System.Security.Authentication;
#nullable enable
namespace FileLiberator
@@ -25,14 +26,22 @@ namespace FileLiberator
public static async Task<AudibleApi.Api> GetApiAsync(this LibraryBook libraryBook)
{
Account account;
using (var accounts = AudibleApiStorage.GetAccountsSettingsPersister())
account = accounts.AccountsSettings.GetAccount(libraryBook.Account, libraryBook.Book.Locale);
using var accounts = AudibleApiStorage.GetAccountsSettingsPersister();
var account = accounts.AccountsSettings.GetAccount(libraryBook.Account, libraryBook.Book.Locale)
?? throw new InvalidCredentialException($"No account found for '{libraryBook.Account}' and locale '{libraryBook.Book.Locale}'");
var apiExtended = await ApiExtended.CreateAsync(account);
return apiExtended.Api;
}
public static bool SupportsWidevine(this AudibleApi.Api api)
{
//TODO: Expose Api's identity maintainer directly instead of using reflection.
var identityProperty = api.GetType().GetProperty("_identityMaintainer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
return identityProperty?.GetValue(api) is AudibleApi.Authorization.IIdentityMaintainer identityMaintainer
&& identityMaintainer.DeviceType == AudibleApi.Resources.DeviceType;
}
public static LibraryBookDto ToDto(this LibraryBook libraryBook)
{
using var persister = AudibleApiStorage.GetAccountsSettingsPersister();

View File

@@ -39,7 +39,7 @@ namespace LibationAvalonia.Controls.Settings
{
using var accounts = AudibleApiStorage.GetAccountsSettingsPersister();
if (!accounts.AccountsSettings.Accounts.Any(a => a.IdentityTokens.DeviceType == AudibleApi.Resources.DeviceType))
if (!accounts.AccountsSettings.Accounts.All(a => a.IdentityTokens.DeviceType == AudibleApi.Resources.DeviceType))
{
if (VisualRoot is Window parent)
{

View File

@@ -224,7 +224,7 @@ namespace LibationWinForms.Dialogs
{
using var accounts = AudibleApiStorage.GetAccountsSettingsPersister();
if (!accounts.AccountsSettings.Accounts.Any(a => a.IdentityTokens.DeviceType == AudibleApi.Resources.DeviceType))
if (!accounts.AccountsSettings.Accounts.All(a => a.IdentityTokens.DeviceType == AudibleApi.Resources.DeviceType))
{
var choice = MessageBox.Show(this,
"In order to enable widevine content, Libation will need to log into your accounts again.\r\n\r\n" +