// // Copyright 2017 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // #import "OWSOutgoingSentMessageTranscript.h" #import "TSOutgoingMessage.h" #import "TSThread.h" #import NS_ASSUME_NONNULL_BEGIN @interface TSOutgoingMessage (OWSOutgoingSentMessageTranscript) /** * Normally this is private, but we need to embed this * data structure within our own. * * recipientId is nil when building "sent" sync messages for messages * sent to groups. */ - (nullable SSKProtoDataMessage *)buildDataMessage:(TSThread *)thread transaction:(SDSAnyReadTransaction *)transaction; @end #pragma mark - @interface OWSOutgoingSentMessageTranscript () // sentRecipientAddress is the recipient of message, for contact thread messages. // It is used to identify the thread/conversation to desktop. @property (nonatomic, readonly, nullable) SignalServiceAddress *sentRecipientAddress; @end #pragma mark - @implementation OWSOutgoingSentMessageTranscript - (instancetype)initWithLocalThread:(TSThread *)localThread messageThread:(TSThread *)messageThread outgoingMessage:(TSOutgoingMessage *)message isRecipientUpdate:(BOOL)isRecipientUpdate transaction:(SDSAnyReadTransaction *)transaction { OWSAssertDebug(message != nil); OWSAssertDebug(localThread != nil); OWSAssertDebug(messageThread != nil); // The sync message's timestamp must match the original outgoing message's timestamp. self = [super initWithTimestamp:message.timestamp thread:localThread transaction:transaction]; if (!self) { return self; } _message = message; _messageThread = messageThread; _isRecipientUpdate = isRecipientUpdate; if ([messageThread isKindOfClass:[TSContactThread class]]) { TSContactThread *contactThread = (TSContactThread *)messageThread; _sentRecipientAddress = contactThread.contactAddress; } return self; } - (nullable instancetype)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (!self) { return self; } if (_sentRecipientAddress == nil) { NSString *phoneNumber = [coder decodeObjectForKey:@"sentRecipientId"]; _sentRecipientAddress = [SignalServiceAddress legacyAddressWithServiceIdString:nil phoneNumber:phoneNumber]; OWSAssertDebug(_sentRecipientAddress.isValid); } return self; } - (BOOL)isUrgent { return NO; } - (nullable SSKProtoSyncMessageBuilder *)syncMessageBuilderWithTransaction:(SDSAnyReadTransaction *)transaction { SSKProtoSyncMessageSentBuilder *sentBuilder = [SSKProtoSyncMessageSent builder]; [sentBuilder setTimestamp:self.timestamp]; [sentBuilder setDestinationE164:self.sentRecipientAddress.phoneNumber]; [sentBuilder setDestinationServiceID:self.sentRecipientAddress.serviceIdString]; [sentBuilder setIsRecipientUpdate:self.isRecipientUpdate]; if (![self prepareDataSyncMessageContentWithSentBuilder:sentBuilder tx:transaction]) { return nil; } for (SignalServiceAddress *recipientAddress in self.message.sentRecipientAddresses) { TSOutgoingMessageRecipientState *_Nullable recipientState = [self.message recipientStateForAddress:recipientAddress]; if (!recipientState) { OWSFailDebug(@"missing recipient state for: %@", recipientAddress); continue; } if (recipientState.state != OWSOutgoingMessageRecipientStateSent) { OWSFailDebug(@"unexpected recipient state for: %@", recipientAddress); continue; } NSError *error; SSKProtoSyncMessageSentUnidentifiedDeliveryStatusBuilder *statusBuilder = [SSKProtoSyncMessageSentUnidentifiedDeliveryStatus builder]; [statusBuilder setDestinationServiceID:recipientAddress.serviceIdString]; [statusBuilder setUnidentified:recipientState.wasSentByUD]; SSKProtoSyncMessageSentUnidentifiedDeliveryStatus *status = [statusBuilder buildInfallibly]; [sentBuilder addUnidentifiedStatus:status]; } NSError *error; SSKProtoSyncMessageSent *_Nullable sentProto = [sentBuilder buildAndReturnError:&error]; if (error || !sentProto) { OWSFailDebug(@"could not build protobuf: %@", error); return nil; } SSKProtoSyncMessageBuilder *syncMessageBuilder = [SSKProtoSyncMessage builder]; [syncMessageBuilder setSent:sentProto]; return syncMessageBuilder; } - (NSSet *)relatedUniqueIds { return [[super relatedUniqueIds] setByAddingObjectsFromArray:@[ self.message.uniqueId ]]; } @end NS_ASSUME_NONNULL_END