Add sync message support for edit message.

This commit is contained in:
Clark
2023-04-19 12:19:29 -04:00
committed by Cody Henthorne
parent 85787ba1df
commit 5ddd7cdb9e
8 changed files with 495 additions and 65 deletions

View File

@@ -49,7 +49,7 @@ object EditMessageProcessor {
log(envelope.timestamp, "[handleEditMessage] Edit message for " + editMessage.targetSentTimestamp)
var targetMessage: MediaMmsMessageRecord? = SignalDatabase.messages.getMessageFor(editMessage.targetSentTimestamp, senderRecipient.id) as MediaMmsMessageRecord
var targetMessage: MediaMmsMessageRecord? = SignalDatabase.messages.getMessageFor(editMessage.targetSentTimestamp, senderRecipient.id) as? MediaMmsMessageRecord
val targetThreadRecipient: Recipient? = if (targetMessage != null) SignalDatabase.threads.getRecipientForThreadId(targetMessage.threadId) else null
if (targetMessage == null || targetThreadRecipient == null) {

View File

@@ -86,6 +86,7 @@ import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry
import org.thoughtcrime.securesms.util.FeatureFlags
import org.thoughtcrime.securesms.util.IdentityUtil
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.MessageConstraintsUtil
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.util.Util
import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata
@@ -164,6 +165,11 @@ object SyncMessageProcessor {
return
}
if (sent.hasEditMessage()) {
handleSynchronizeSentEditMessage(context, envelope, sent, senderRecipient, earlyMessageCacheEntry)
return
}
val dataMessage = sent.message
val groupId: GroupId.V2? = if (dataMessage.hasGroupContext) GroupId.v2(dataMessage.groupV2.groupMasterKey) else null
@@ -229,6 +235,170 @@ object SyncMessageProcessor {
}
}
@Throws(MmsException::class)
private fun handleSynchronizeSentEditMessage(
context: Context,
envelope: Envelope,
sent: Sent,
senderRecipient: Recipient,
earlyMessageCacheEntry: EarlyMessageCacheEntry?
) {
val targetSentTimestamp: Long = sent.editMessage.targetSentTimestamp
val targetMessage: MessageRecord? = SignalDatabase.messages.getMessageFor(targetSentTimestamp, senderRecipient.id)
val senderRecipientId = senderRecipient.id
if (targetMessage == null) {
warn(envelope.timestamp, "[handleSynchronizeSentEditMessage] Could not find matching message! targetTimestamp: $targetSentTimestamp author: $senderRecipientId")
if (earlyMessageCacheEntry != null) {
ApplicationDependencies.getEarlyMessageCache().store(senderRecipientId, targetSentTimestamp, earlyMessageCacheEntry)
PushProcessEarlyMessagesJob.enqueue()
}
} else if (MessageConstraintsUtil.isValidEditMessageReceive(targetMessage, senderRecipient, envelope.serverTimestamp)) {
val message = sent.editMessage.dataMessage
val toRecipient: Recipient = if (message.hasGroupContext) {
Recipient.externalPossiblyMigratedGroup(GroupId.v2(message.groupV2.groupMasterKey))
} else {
Recipient.externalPush(ServiceId.parseOrThrow(sent.destinationUuid))
}
if (message.isMediaMessage) {
handleSynchronizeSentEditMediaMessage(context, targetMessage, toRecipient, sent, message, envelope.timestamp)
} else {
handleSynchronizeSentEditTextMessage(targetMessage, toRecipient, sent, message, envelope.timestamp)
}
} else {
warn(envelope.timestamp, "[handleSynchronizeSentEditMessage] Invalid message edit! editTime: ${envelope.serverTimestamp}, targetTime: ${targetMessage.serverTimestamp}, sendAuthor: $senderRecipientId, targetAuthor: ${targetMessage.fromRecipient.id}")
}
}
private fun handleSynchronizeSentEditTextMessage(
targetMessage: MessageRecord,
toRecipient: Recipient,
sent: Sent,
message: DataMessage,
envelopeTimestamp: Long
) {
log(envelopeTimestamp, "Synchronize sent edit text message for message: ${targetMessage.id}")
val body = message.body ?: ""
val bodyRanges = message.bodyRangesList.filterNot { it.hasMentionUuid() }.toBodyRangeList()
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(toRecipient)
val isGroup = toRecipient.isGroup
val messageId: Long
if (isGroup) {
val outgoingMessage = OutgoingMessage(
recipient = toRecipient,
body = body,
timestamp = sent.timestamp,
expiresIn = targetMessage.expiresIn,
isSecure = true,
bodyRanges = bodyRanges,
messageToEdit = targetMessage.id
)
messageId = SignalDatabase.messages.insertMessageOutbox(outgoingMessage, threadId, false, GroupReceiptTable.STATUS_UNKNOWN, null)
updateGroupReceiptStatus(sent, messageId, toRecipient.requireGroupId())
} else {
val outgoingTextMessage = OutgoingMessage(
threadRecipient = toRecipient,
sentTimeMillis = sent.timestamp,
body = body,
expiresIn = targetMessage.expiresIn,
isUrgent = true,
isSecure = true,
bodyRanges = bodyRanges,
messageToEdit = targetMessage.id
)
messageId = SignalDatabase.messages.insertMessageOutbox(outgoingTextMessage, threadId, false, null)
SignalDatabase.messages.markUnidentified(messageId, sent.isUnidentified(toRecipient.serviceId.orNull()))
}
SignalDatabase.threads.update(threadId, true)
SignalDatabase.messages.markAsSent(messageId, true)
if (targetMessage.expireStarted > 0) {
SignalDatabase.messages.markExpireStarted(messageId, targetMessage.expireStarted)
ApplicationDependencies.getExpiringMessageManager().scheduleDeletion(messageId, true, targetMessage.expireStarted, targetMessage.expireStarted)
}
if (toRecipient.isSelf) {
SignalDatabase.messages.incrementDeliveryReceiptCount(sent.timestamp, toRecipient.id, System.currentTimeMillis())
SignalDatabase.messages.incrementReadReceiptCount(sent.timestamp, toRecipient.id, System.currentTimeMillis())
}
}
private fun handleSynchronizeSentEditMediaMessage(
context: Context,
targetMessage: MessageRecord,
toRecipient: Recipient,
sent: Sent,
message: DataMessage,
envelopeTimestamp: Long
) {
log(envelopeTimestamp, "Synchronize sent edit media message for: ${targetMessage.id}")
val quote: QuoteModel? = DataMessageProcessor.getValidatedQuote(context, envelopeTimestamp, message)
val sharedContacts: List<Contact> = DataMessageProcessor.getContacts(message)
val previews: List<LinkPreview> = DataMessageProcessor.getLinkPreviews(message.previewList, message.body ?: "", false)
val mentions: List<Mention> = DataMessageProcessor.getMentions(message.bodyRangesList)
val viewOnce: Boolean = message.isViewOnce
val bodyRanges: BodyRangeList? = message.bodyRangesList.toBodyRangeList()
val syncAttachments = message.attachmentsList.toPointers().filter {
MediaUtil.SlideType.LONG_TEXT == MediaUtil.getSlideTypeFromContentType(it.contentType)
}
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(toRecipient)
val messageId: Long
val attachments: List<DatabaseAttachment>
val mediaMessage = OutgoingMessage(
recipient = toRecipient,
body = message.body ?: "",
attachments = syncAttachments.ifEmpty { (targetMessage as? MediaMmsMessageRecord)?.slideDeck?.asAttachments() ?: emptyList() },
timestamp = sent.timestamp,
expiresIn = targetMessage.expiresIn,
viewOnce = viewOnce,
quote = quote,
contacts = sharedContacts,
previews = previews,
mentions = mentions,
bodyRanges = bodyRanges,
isSecure = true,
messageToEdit = targetMessage.id
)
SignalDatabase.messages.beginTransaction()
try {
messageId = SignalDatabase.messages.insertMessageOutbox(mediaMessage, threadId, false, GroupReceiptTable.STATUS_UNKNOWN, null)
if (toRecipient.isGroup) {
updateGroupReceiptStatus(sent, messageId, toRecipient.requireGroupId())
} else {
SignalDatabase.messages.markUnidentified(messageId, sent.isUnidentified(toRecipient.serviceId.orNull()))
}
SignalDatabase.messages.markAsSent(messageId, true)
attachments = SignalDatabase.attachments.getAttachmentsForMessage(messageId)
if (targetMessage.expireStarted > 0) {
SignalDatabase.messages.markExpireStarted(messageId, targetMessage.expireStarted)
ApplicationDependencies.getExpiringMessageManager().scheduleDeletion(messageId, true, targetMessage.expireStarted, targetMessage.expireStarted)
}
if (toRecipient.isSelf) {
SignalDatabase.messages.incrementDeliveryReceiptCount(sent.timestamp, toRecipient.id, System.currentTimeMillis())
SignalDatabase.messages.incrementReadReceiptCount(sent.timestamp, toRecipient.id, System.currentTimeMillis())
}
SignalDatabase.messages.setTransactionSuccessful()
} finally {
SignalDatabase.messages.endTransaction()
}
if (syncAttachments.isNotEmpty()) {
for (attachment in attachments) {
ApplicationDependencies.getJobManager().add(AttachmentDownloadJob(messageId, attachment.attachmentId, false))
}
}
}
@Throws(MmsException::class)
private fun handleSynchronizeSentStoryMessage(envelope: Envelope, sent: Sent) {
log(envelope.timestamp, "Synchronize sent story message for " + sent.timestamp)

View File

@@ -52,7 +52,7 @@ object MessageConstraintsUtil {
@JvmStatic
fun isValidEditMessageSend(targetMessage: MessageRecord, currentTime: Long): Boolean {
return isValidRemoteDeleteSend(targetMessage, currentTime) &&
targetMessage.revisionNumber < 10 &&
targetMessage.revisionNumber < MAX_EDIT_COUNT &&
!targetMessage.isViewOnceMessage() &&
!targetMessage.hasAudio() &&
!targetMessage.hasSharedContact()