// // Copyright 2019 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // import Foundation public import LibSignalClient public typealias RecipientUniqueId = String public enum RecipientIdError: Error, IsRetryableProvider { /// We can't use the Pni because it's been replaced by an Aci. case mustNotUsePniBecauseAciExists public var isRetryableProvider: Bool { // Allow retries so that we send to the Aci instead of the Pni. return true } } public final class RecipientIdFinder { private let recipientDatabaseTable: RecipientDatabaseTable private let recipientFetcher: RecipientFetcher public init( recipientDatabaseTable: RecipientDatabaseTable, recipientFetcher: RecipientFetcher ) { self.recipientFetcher = recipientFetcher self.recipientDatabaseTable = recipientDatabaseTable } public func recipientUniqueId(for serviceId: ServiceId, tx: DBReadTransaction) -> Result? { guard let recipient = recipientDatabaseTable.fetchRecipient(serviceId: serviceId, transaction: tx) else { return nil } return recipientUniqueIdResult(for: serviceId, recipient: recipient) } public func recipientUniqueId(for address: SignalServiceAddress, tx: DBReadTransaction) -> Result? { guard let recipient = DependenciesBridge.shared.recipientDatabaseTable .fetchRecipient(address: address, tx: tx) else { return nil } return recipientUniqueIdResult(for: address.serviceId, recipient: recipient) } public func ensureRecipientUniqueId(for serviceId: ServiceId, tx: DBWriteTransaction) -> Result { let recipient = recipientFetcher.fetchOrCreate(serviceId: serviceId, tx: tx) return recipientUniqueIdResult(for: serviceId, recipient: recipient) } private func recipientUniqueIdResult(for serviceId: ServiceId?, recipient: SignalRecipient) -> Result { if serviceId is Pni, recipient.aciString != nil { return .failure(.mustNotUsePniBecauseAciExists) } return .success(recipient.uniqueId) } }