diff --git a/Source/AudibleUtilities/Mkb79Auth.cs b/Source/AudibleUtilities/Mkb79Auth.cs index 4731a806..e58e6041 100644 --- a/Source/AudibleUtilities/Mkb79Auth.cs +++ b/Source/AudibleUtilities/Mkb79Auth.cs @@ -237,6 +237,12 @@ public partial class Mkb79Auth return account; } + /// + /// The exported file names one marketplace - the one this account is registered with - because that is all + /// the format holds: a single locale_code alongside a single device registration. audible-cli switches + /// marketplaces on its own from those same tokens, so nothing is lost to it. Any additional marketplaces + /// Libation reads for this account are its own bookkeeping and have no slot here. + /// public static Mkb79Auth FromAccount(Account account) => new() { diff --git a/Source/AudibleUtilities/Mkb79AuthImporter.cs b/Source/AudibleUtilities/Mkb79AuthImporter.cs index 82b21ccb..a4227dba 100644 --- a/Source/AudibleUtilities/Mkb79AuthImporter.cs +++ b/Source/AudibleUtilities/Mkb79AuthImporter.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System; using System.Threading.Tasks; namespace AudibleUtilities; @@ -10,10 +10,37 @@ public enum Mkb79ImportOutcome InvalidFile, } -public sealed record Mkb79ImportResult(Mkb79ImportOutcome Outcome, Account? Account = null, string? Message = null); +/// +/// For , the account already scanning that marketplace. It may +/// be one registered with it, or one carrying it as an additional marketplace. +/// +public sealed record Mkb79ImportResult( + Mkb79ImportOutcome Outcome, + Account? Account = null, + string? Message = null, + Account? ClaimedBy = null); public static class Mkb79AuthImporter { + /// + /// Why a duplicate import was refused, in the same words everywhere it is refused. Naming the account that + /// already reads the marketplace matters now that it need not be a row registered with it - it may be one + /// reading it as an additional marketplace, which is not obvious from the accounts grid. + /// + public static string DuplicateMessage(Mkb79ImportResult result) + { + var locale = result.Account?.Locale?.Name ?? "[unknown]"; + + if (result.ClaimedBy is { } claimedBy && claimedBy.Locale?.Name != locale) + return $"The '{locale}' marketplace is already scanned by the account " + + $"{AccountCredentialStatus.FormatAccountLabel(claimedBy)}, as an additional marketplace. " + + "Nothing was imported."; + + return "An account with that account id and country already exists." + + $"{Environment.NewLine}Account ID: {result.Account?.AccountId}" + + $"{Environment.NewLine}Country: {locale}"; + } + /// /// Deserialize mkb79/audible-cli JSON, refresh tokens, and add the account if not already present. /// @@ -32,11 +59,12 @@ public static class Mkb79AuthImporter using var persister = AudibleApiStorage.GetAccountsSettingsPersister(); - if (persister.AccountsSettings.Accounts.Any(a => - a.AccountId == account.AccountId && a.IdentityTokens?.Locale.Name == account.Locale?.Name)) - { - return new Mkb79ImportResult(Mkb79ImportOutcome.DuplicateAccount, account); - } + // An mkb79 file names one marketplace, and a marketplace can only be scanned by one account. Ask about + // every claim on it, not just registrations: an existing account may already be reading this marketplace + // as an additional one, in which case importing would scan it twice. + var claimedBy = persister.AccountsSettings.GetAccountClaimingMarketplace(account.AccountId, account.Locale?.Name); + if (claimedBy is not null) + return new Mkb79ImportResult(Mkb79ImportOutcome.DuplicateAccount, account, ClaimedBy: claimedBy); persister.AccountsSettings.Add(account); return new Mkb79ImportResult(Mkb79ImportOutcome.Success, account); diff --git a/Source/LibationAvalonia/Dialogs/AccountsDialog.axaml b/Source/LibationAvalonia/Dialogs/AccountsDialog.axaml index c0cf27b4..1dc81128 100644 --- a/Source/LibationAvalonia/Dialogs/AccountsDialog.axaml +++ b/Source/LibationAvalonia/Dialogs/AccountsDialog.axaml @@ -87,6 +87,23 @@ + + + + +