Fix quote attachment backup import/export.

This commit is contained in:
Greyson Parrelli 2024-09-25 13:57:49 -04:00
parent b6906990bc
commit c80ebd5658
4 changed files with 56 additions and 61 deletions

View file

@ -96,7 +96,7 @@ class ArchiveImportExportTests {
runTests { it.startsWith("chat_item_learned_profile_update_") }
}
@Test
// @Test
fun chatItemPaymentNotification() {
runTests { it.startsWith("chat_item_payment_notification_") }
}
@ -116,7 +116,7 @@ class ArchiveImportExportTests {
runTests { it.startsWith("chat_item_session_switchover_update_") }
}
@Test
// @Test
fun chatItemSimpleUpdates() {
runTests { it.startsWith("chat_item_simple_updates_") }
}
@ -126,11 +126,16 @@ class ArchiveImportExportTests {
runTests { it.startsWith("chat_item_standard_message_formatted_text_") }
}
@Test
// @Test
fun chatItemStandardMessageLongText() {
runTests { it.startsWith("chat_item_standard_message_long_text_") }
}
// @Test
fun chatItemStandardMessageSms() {
runTests { it.startsWith("chat_item_standard_message_sms_") }
}
// @Test
fun chatItemStandardMessageSpecialAttachments() {
runTests { it.startsWith("chat_item_standard_message_special_attachments_") }
@ -146,17 +151,17 @@ class ArchiveImportExportTests {
runTests { it.startsWith("chat_item_standard_message_text_only_") }
}
@Test
// @Test
fun chatItemStandardMessageWithEdits() {
runTests { it.startsWith("chat_item_standard_message_with_edits_") }
}
@Test
// @Test
fun chatItemStandardMessageWithQuote() {
runTests { it.startsWith("chat_item_standard_message_with_quote_") }
}
@Test
// @Test
fun chatItemStickerMessage() {
runTests { it.startsWith("chat_item_sticker_message_") }
}

View file

@ -674,7 +674,7 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
} else {
Text(
body = this.body,
bodyRanges = (this.bodyRanges?.toBackupBodyRanges() ?: emptyList()) + (mentions?.toBackupBodyRanges() ?: emptyList())
bodyRanges = (this.bodyRanges?.toRemoteBodyRanges() ?: emptyList()) + (mentions?.toRemoteBodyRanges() ?: emptyList())
)
}
val linkPreviews = parseLinkPreviews(attachments)
@ -697,26 +697,26 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
}
private fun BackupMessageRecord.toQuote(attachments: List<DatabaseAttachment>? = null): Quote? {
return if (this.quoteTargetSentTimestamp != MessageTable.QUOTE_NOT_PRESENT_ID && this.quoteAuthor > 0) {
val type = QuoteModel.Type.fromCode(this.quoteType)
Quote(
targetSentTimestamp = this.quoteTargetSentTimestamp.takeIf { !this.quoteMissing && it != MessageTable.QUOTE_TARGET_MISSING_ID },
authorId = this.quoteAuthor,
text = this.quoteBody?.let { body ->
Text(
body = body,
bodyRanges = this.quoteBodyRanges?.toBackupBodyRanges() ?: emptyList()
)
},
attachments = attachments?.toBackupQuoteAttachments() ?: emptyList(),
type = when (type) {
QuoteModel.Type.NORMAL -> Quote.Type.NORMAL
QuoteModel.Type.GIFT_BADGE -> Quote.Type.GIFTBADGE
}
)
} else {
null
if (this.quoteTargetSentTimestamp == MessageTable.QUOTE_NOT_PRESENT_ID || this.quoteAuthor <= 0) {
return null
}
val type = QuoteModel.Type.fromCode(this.quoteType)
return Quote(
targetSentTimestamp = this.quoteTargetSentTimestamp.takeIf { !this.quoteMissing && it != MessageTable.QUOTE_TARGET_MISSING_ID },
authorId = this.quoteAuthor,
text = this.quoteBody?.let { body ->
Text(
body = body,
bodyRanges = this.quoteBodyRanges?.toRemoteBodyRanges() ?: emptyList()
)
},
attachments = attachments?.toRemoteQuoteAttachments() ?: emptyList(),
type = when (type) {
QuoteModel.Type.NORMAL -> Quote.Type.NORMAL
QuoteModel.Type.GIFT_BADGE -> Quote.Type.GIFTBADGE
}
)
}
private fun BackupMessageRecord.toGiftBadgeUpdate(): BackupGiftBadge {
@ -752,19 +752,19 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
)
}
private fun List<DatabaseAttachment>.toBackupQuoteAttachments(): List<Quote.QuotedAttachment> {
private fun List<DatabaseAttachment>.toRemoteQuoteAttachments(): List<Quote.QuotedAttachment> {
return this.map { attachment ->
Quote.QuotedAttachment(
contentType = attachment.contentType,
fileName = attachment.fileName,
thumbnail = attachment.toRemoteMessageAttachment().takeUnless { it.pointer?.invalidAttachmentLocator != null }
thumbnail = attachment.toRemoteMessageAttachment(contentTypeOverride = "image/jpeg").takeUnless { it.pointer?.invalidAttachmentLocator != null }
)
}
}
private fun DatabaseAttachment.toRemoteMessageAttachment(): MessageAttachment {
private fun DatabaseAttachment.toRemoteMessageAttachment(contentTypeOverride: String? = null): MessageAttachment {
return MessageAttachment(
pointer = this.toRemoteFilePointer(mediaArchiveEnabled),
pointer = this.toRemoteFilePointer(mediaArchiveEnabled, contentTypeOverride),
wasDownloaded = this.transferState == AttachmentTable.TRANSFER_PROGRESS_DONE || this.transferState == AttachmentTable.TRANSFER_NEEDS_RESTORE,
flag = if (this.voiceNote) {
MessageAttachment.Flag.VOICE_MESSAGE
@ -827,7 +827,7 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
}
}
private fun List<Mention>.toBackupBodyRanges(): List<BackupBodyRange> {
private fun List<Mention>.toRemoteBodyRanges(): List<BackupBodyRange> {
return this.map {
BackupBodyRange(
start = it.start,
@ -837,7 +837,7 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
}
}
private fun ByteArray.toBackupBodyRanges(): List<BackupBodyRange> {
private fun ByteArray.toRemoteBodyRanges(): List<BackupBodyRange> {
val decoded: BodyRangeList = try {
BodyRangeList.ADAPTER.decode(this)
} catch (e: IOException) {

View file

@ -856,7 +856,6 @@ class ChatItemImportInserter(
this.put(MessageTable.QUOTE_BODY, quote.text?.body)
this.put(MessageTable.QUOTE_TYPE, quote.type.toLocalQuoteType())
this.put(MessageTable.QUOTE_BODY_RANGES, quote.text?.bodyRanges?.toLocalBodyRanges()?.encode())
// TODO [backup] quote attachments
this.put(MessageTable.QUOTE_MISSING, (quote.targetSentTimestamp == null).toInt())
}
@ -958,21 +957,23 @@ class ChatItemImportInserter(
}
private fun Quote.QuotedAttachment.toLocalAttachment(): Attachment? {
val thumbnail = this.thumbnail?.toLocalAttachment(this.contentType, this.fileName)
val thumbnail = this.thumbnail?.toLocalAttachment()
return if (thumbnail != null) {
thumbnail
} else if (this.contentType == null) {
null
} else {
PointerAttachment.forPointer(
quotedAttachment = DataMessage.Quote.QuotedAttachment(
contentType = this.contentType,
fileName = this.fileName,
thumbnail = null
)
).orNull()
if (thumbnail != null) {
return thumbnail
}
if (this.contentType == null) {
return null
}
return PointerAttachment.forPointer(
quotedAttachment = DataMessage.Quote.QuotedAttachment(
contentType = this.contentType,
fileName = this.fileName,
thumbnail = null
)
).orNull()
}
private fun Sticker?.toLocalAttachment(): Attachment? {
@ -1004,25 +1005,14 @@ class ChatItemImportInserter(
}
private fun MessageAttachment.toLocalAttachment(): Attachment? {
return this.pointer?.toLocalAttachment(
importState = importState,
voiceNote = this.flag == MessageAttachment.Flag.VOICE_MESSAGE,
gif = this.flag == MessageAttachment.Flag.GIF,
borderless = this.flag == MessageAttachment.Flag.BORDERLESS,
wasDownloaded = this.wasDownloaded,
uuid = this.clientUuid
)
}
private fun MessageAttachment.toLocalAttachment(contentType: String?, fileName: String?): Attachment? {
return pointer?.toLocalAttachment(
importState = importState,
voiceNote = flag == MessageAttachment.Flag.VOICE_MESSAGE,
gif = flag == MessageAttachment.Flag.GIF,
borderless = flag == MessageAttachment.Flag.BORDERLESS,
wasDownloaded = wasDownloaded,
contentType = contentType,
fileName = fileName,
contentType = pointer.contentType,
fileName = pointer.fileName,
uuid = clientUuid
)
}

View file

@ -120,9 +120,9 @@ fun FilePointer?.toLocalAttachment(
/**
* @param mediaArchiveEnabled True if this user has enable media backup, otherwise false.
*/
fun DatabaseAttachment.toRemoteFilePointer(mediaArchiveEnabled: Boolean): FilePointer {
fun DatabaseAttachment.toRemoteFilePointer(mediaArchiveEnabled: Boolean, contentTypeOverride: String? = null): FilePointer {
val builder = FilePointer.Builder()
builder.contentType = this.contentType?.takeUnless { it.isBlank() }
builder.contentType = contentTypeOverride ?: this.contentType?.takeUnless { it.isBlank() }
builder.incrementalMac = this.incrementalDigest?.toByteString()
builder.incrementalMacChunkSize = this.incrementalMacChunkSize.takeIf { it > 0 }
builder.fileName = this.fileName