From 1b2a80d7864460c9d1fc913d6d7c4c0083a0cde8 Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Mon, 21 Oct 2024 11:36:07 +1100 Subject: [PATCH] SES-2811 - Do not attempt to send a failed message marked as deleted --- .../attachments/DatabaseAttachmentProvider.kt | 6 +++++ .../securesms/database/MmsDatabase.kt | 17 ++++++++++++++ .../securesms/database/SmsDatabase.java | 23 +++++++++++++++++++ .../database/MessageDataProvider.kt | 1 + .../messaging/jobs/MessageSendJob.kt | 12 +++++++++- .../sending_receiving/MessageSender.kt | 8 ++++++- 6 files changed, 65 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/attachments/DatabaseAttachmentProvider.kt b/app/src/main/java/org/thoughtcrime/securesms/attachments/DatabaseAttachmentProvider.kt index d74174fecb..06e344a239 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/attachments/DatabaseAttachmentProvider.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/attachments/DatabaseAttachmentProvider.kt @@ -145,6 +145,12 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper) return smsDatabase.isOutgoingMessage(timestamp) || mmsDatabase.isOutgoingMessage(timestamp) } + override fun isDeletedMessage(timestamp: Long): Boolean { + val smsDatabase = DatabaseComponent.get(context).smsDatabase() + val mmsDatabase = DatabaseComponent.get(context).mmsDatabase() + return smsDatabase.isDeletedMessage(timestamp) || mmsDatabase.isDeletedMessage(timestamp) + } + override fun handleSuccessfulAttachmentUpload(attachmentId: Long, attachmentStream: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: UploadResult) { val database = DatabaseComponent.get(context).attachmentDatabase() val databaseAttachment = getDatabaseAttachment(attachmentId) ?: return diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt index 63460744f6..60c4de6883 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt @@ -106,6 +106,23 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa .any { MmsSmsColumns.Types.isOutgoingMessageType(it) } } + fun isDeletedMessage(timestamp: Long): Boolean = + databaseHelper.writableDatabase.query( + TABLE_NAME, + arrayOf(ID, THREAD_ID, MESSAGE_BOX, ADDRESS), + DATE_SENT + " = ?", + arrayOf(timestamp.toString()), + null, + null, + null, + null + ).use { cursor -> + cursor.asSequence() + .map { cursor.getColumnIndexOrThrow(MESSAGE_BOX) } + .map(cursor::getLong) + .any { MmsSmsColumns.Types.isDeletedMessage(it) } + } + fun incrementReceiptCount( messageId: SyncMessageId, timestamp: Long, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 5088b76d29..ed7945e8a3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -243,6 +243,7 @@ public class SmsDatabase extends MessagingDatabase { contentValues.put(READ, 1); contentValues.put(BODY, displayedMessage); contentValues.put(HAS_MENTION, 0); + contentValues.put(STATUS, Status.STATUS_NONE); database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {String.valueOf(messageId)}); updateTypeBitmask(messageId, Types.BASE_TYPE_MASK, @@ -299,6 +300,28 @@ public class SmsDatabase extends MessagingDatabase { return isOutgoing; } + public boolean isDeletedMessage(long timestamp) { + SQLiteDatabase database = databaseHelper.getWritableDatabase(); + Cursor cursor = null; + boolean isDeleted = false; + + try { + cursor = database.query(TABLE_NAME, new String[] { ID, THREAD_ID, ADDRESS, TYPE }, + DATE_SENT + " = ?", new String[] { String.valueOf(timestamp) }, + null, null, null, null); + + while (cursor.moveToNext()) { + if (Types.isDeletedMessage(cursor.getLong(cursor.getColumnIndexOrThrow(TYPE)))) { + isDeleted = true; + } + } + } finally { + if (cursor != null) cursor.close(); + } + + return isDeleted; + } + public void incrementReceiptCount(SyncMessageId messageId, boolean deliveryReceipt, boolean readReceipt) { SQLiteDatabase database = databaseHelper.getWritableDatabase(); Cursor cursor = null; diff --git a/libsession/src/main/java/org/session/libsession/database/MessageDataProvider.kt b/libsession/src/main/java/org/session/libsession/database/MessageDataProvider.kt index 8e6ed68993..230e23e52c 100644 --- a/libsession/src/main/java/org/session/libsession/database/MessageDataProvider.kt +++ b/libsession/src/main/java/org/session/libsession/database/MessageDataProvider.kt @@ -38,6 +38,7 @@ interface MessageDataProvider { fun updateAudioAttachmentDuration(attachmentId: AttachmentId, durationMs: Long, threadId: Long) fun isMmsOutgoing(mmsMessageId: Long): Boolean fun isOutgoingMessage(timestamp: Long): Boolean + fun isDeletedMessage(timestamp: Long): Boolean fun handleSuccessfulAttachmentUpload(attachmentId: Long, attachmentStream: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: UploadResult) fun handleFailedAttachmentUpload(attachmentId: Long) fun getMessageForQuote(timestamp: Long, author: Address): Triple? diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt index 52d56184cc..2010a58e61 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt @@ -37,6 +37,13 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job { val message = message as? VisibleMessage val storage = MessagingModuleConfiguration.shared.storage + // do not attempt to send if the message is marked as deleted + message?.sentTimestamp?.let{ + if(messageDataProvider.isDeletedMessage(it)){ + return@execute + } + } + val sentTimestamp = this.message.sentTimestamp val sender = storage.getUserPublicKey() if (sentTimestamp != null && sender != null) { @@ -107,7 +114,10 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job { Log.w(TAG, "Failed to send $message::class.simpleName.") val message = message as? VisibleMessage if (message != null) { - if (!MessagingModuleConfiguration.shared.messageDataProvider.isOutgoingMessage(message.sentTimestamp!!)) { + if ( + MessagingModuleConfiguration.shared.messageDataProvider.isDeletedMessage(message.sentTimestamp!!) || + !MessagingModuleConfiguration.shared.messageDataProvider.isOutgoingMessage(message.sentTimestamp!!) + ) { return // The message has been deleted } } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt index 301648f97b..73073532b0 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt @@ -469,9 +469,15 @@ object MessageSender { fun handleFailedMessageSend(message: Message, error: Exception, isSyncMessage: Boolean = false) { val storage = MessagingModuleConfiguration.shared.storage + val timestamp = message.sentTimestamp!! + + // no need to handle if message is marked as deleted + if(MessagingModuleConfiguration.shared.messageDataProvider.isDeletedMessage(message.sentTimestamp!!)){ + return + } + val userPublicKey = storage.getUserPublicKey()!! - val timestamp = message.sentTimestamp!! val author = message.sender ?: userPublicKey if (isSyncMessage) storage.markAsSyncFailed(timestamp, author, error)