Improve backup validation of empty items.

This commit is contained in:
Greyson Parrelli 2025-01-17 15:51:24 -05:00
parent a943186510
commit 0695a01725
3 changed files with 32 additions and 9 deletions

View file

@ -12,7 +12,11 @@ import org.thoughtcrime.securesms.database.CallTable
*/ */
object ExportSkips { object ExportSkips {
fun emptyChatItem(sentTimestamp: Long): String { fun emptyChatItem(sentTimestamp: Long): String {
return log(sentTimestamp, "Completely empty ChatItem (no body or attachments).") return log(sentTimestamp, "Completely empty ChatItem (no inner item is set).")
}
fun emptyStandardMessage(sentTimestamp: Long): String {
return log(sentTimestamp, "Completely empty StandardMessage (no body or attachments).")
} }
fun invalidLongTextChatItem(sentTimestamp: Long): String { fun invalidLongTextChatItem(sentTimestamp: Long): String {

View file

@ -13,7 +13,6 @@ import org.signal.core.util.requireInt
import org.signal.core.util.requireLong import org.signal.core.util.requireLong
import org.thoughtcrime.securesms.backup.v2.proto.Chat import org.thoughtcrime.securesms.backup.v2.proto.Chat
import org.thoughtcrime.securesms.backup.v2.util.ChatStyleConverter import org.thoughtcrime.securesms.backup.v2.util.ChatStyleConverter
import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange
import org.thoughtcrime.securesms.conversation.colors.ChatColors import org.thoughtcrime.securesms.conversation.colors.ChatColors
import org.thoughtcrime.securesms.database.RecipientTable import org.thoughtcrime.securesms.database.RecipientTable
import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.SignalDatabase

View file

@ -297,11 +297,6 @@ class ChatItemArchiveExporter(
} }
else -> { else -> {
if (record.body.isNullOrEmpty() && !extraData.attachmentsById.containsKey(record.id)) {
Log.w(TAG, ExportSkips.emptyChatItem(record.dateSent))
continue
}
val attachments = extraData.attachmentsById[record.id] val attachments = extraData.attachmentsById[record.id]
if (attachments?.isNotEmpty() == true && attachments.all { it.contentType == MediaUtil.LONG_TEXT } && record.body.isNullOrEmpty()) { if (attachments?.isNotEmpty() == true && attachments.all { it.contentType == MediaUtil.LONG_TEXT } && record.body.isNullOrEmpty()) {
Log.w(TAG, ExportSkips.invalidLongTextChatItem(record.dateSent)) Log.w(TAG, ExportSkips.invalidLongTextChatItem(record.dateSent))
@ -313,20 +308,28 @@ class ChatItemArchiveExporter(
if (sticker?.stickerLocator != null) { if (sticker?.stickerLocator != null) {
builder.stickerMessage = sticker.toRemoteStickerMessage(mediaArchiveEnabled = mediaArchiveEnabled, reactions = extraData.reactionsById[id]) builder.stickerMessage = sticker.toRemoteStickerMessage(mediaArchiveEnabled = mediaArchiveEnabled, reactions = extraData.reactionsById[id])
} else { } else {
builder.standardMessage = record.toRemoteStandardMessage( val standardMessage = record.toRemoteStandardMessage(
db = db, db = db,
mediaArchiveEnabled = mediaArchiveEnabled, mediaArchiveEnabled = mediaArchiveEnabled,
reactionRecords = extraData.reactionsById[id], reactionRecords = extraData.reactionsById[id],
mentions = extraData.mentionsById[id], mentions = extraData.mentionsById[id],
attachments = extraData.attachmentsById[record.id] attachments = extraData.attachmentsById[record.id]
) )
if (standardMessage.text == null && standardMessage.attachments.isEmpty()) {
Log.w(TAG, ExportSkips.emptyStandardMessage(record.dateSent))
continue
}
builder.standardMessage = standardMessage
} }
} }
} }
if (record.latestRevisionId == null) { if (record.latestRevisionId == null) {
builder.revisions = revisionMap.remove(record.id)?.repairRevisions(builder) ?: emptyList() builder.revisions = revisionMap.remove(record.id)?.repairRevisions(builder) ?: emptyList()
buffer += builder.build() val chatItem = builder.build().validateChatItem() ?: continue
buffer += chatItem
} else { } else {
var previousEdits = revisionMap[record.latestRevisionId] var previousEdits = revisionMap[record.latestRevisionId]
if (previousEdits == null) { if (previousEdits == null) {
@ -1324,6 +1327,23 @@ private fun <T> ExecutorService.submitTyped(callable: Callable<T>): Future<T> {
return this.submit(callable) return this.submit(callable)
} }
fun ChatItem.validateChatItem(): ChatItem? {
if (this.standardMessage == null &&
this.contactMessage == null &&
this.stickerMessage == null &&
this.remoteDeletedMessage == null &&
this.updateMessage == null &&
this.paymentNotification == null &&
this.giftBadge == null &&
this.viewOnceMessage == null &&
this.directStoryReplyMessage == null
) {
Log.w(TAG, ExportSkips.emptyChatItem(this.dateSent))
return null
}
return this
}
fun List<ChatItem>.repairRevisions(current: ChatItem.Builder): List<ChatItem> { fun List<ChatItem>.repairRevisions(current: ChatItem.Builder): List<ChatItem> {
return if (current.standardMessage != null) { return if (current.standardMessage != null) {
val filtered = this.filter { it.standardMessage != null } val filtered = this.filter { it.standardMessage != null }