Update to latest Backup.proto.

This commit is contained in:
Greyson Parrelli
2024-09-19 07:12:12 -04:00
parent 60bf121974
commit 9a1d5f4dce
6 changed files with 52 additions and 41 deletions

View File

@@ -11,6 +11,7 @@ import org.json.JSONArray
import org.json.JSONException
import org.signal.core.util.Base64
import org.signal.core.util.Hex
import org.signal.core.util.emptyIfNull
import org.signal.core.util.logging.Log
import org.signal.core.util.orNull
import org.signal.core.util.requireBlob
@@ -636,8 +637,7 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
familyName = familyName,
prefix = prefix,
suffix = suffix,
middleName = middleName,
displayName = displayName
middleName = middleName
)
}
@@ -699,9 +699,11 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
Quote(
targetSentTimestamp = this.quoteTargetSentTimestamp.takeIf { !this.quoteMissing && it != MessageTable.QUOTE_TARGET_MISSING_ID },
authorId = this.quoteAuthor,
text = this.quoteBody,
text = Text(
body = this.quoteBody.emptyIfNull(),
bodyRanges = this.quoteBodyRanges?.toBackupBodyRanges() ?: emptyList()
),
attachments = attachments?.toBackupQuoteAttachments() ?: emptyList(),
bodyRanges = this.quoteBodyRanges?.toBackupBodyRanges() ?: emptyList(),
type = when (type) {
QuoteModel.Type.NORMAL -> Quote.Type.NORMAL
QuoteModel.Type.GIFT_BADGE -> Quote.Type.GIFTBADGE
@@ -906,8 +908,7 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
emoji = it.emoji,
authorId = it.author.toLong(),
sentTimestamp = it.dateSent,
receivedTimestamp = it.dateReceived,
sortOrder = 0 // TODO [backup] make this it.dateReceived once comparator support is added
sortOrder = it.dateReceived
)
} ?: emptyList()
}
@@ -928,12 +929,12 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
when {
this.identityMismatchRecipientIds.contains(this.toRecipientId) -> {
statusBuilder.failed = SendStatus.Failed(
identityKeyMismatch = true
reason = SendStatus.Failed.FailureReason.IDENTITY_KEY_MISMATCH
)
}
this.networkFailureRecipientIds.contains(this.toRecipientId) -> {
statusBuilder.failed = SendStatus.Failed(
network = true
reason = SendStatus.Failed.FailureReason.NETWORK
)
}
this.baseType == MessageTypes.BASE_SENT_TYPE -> {
@@ -973,12 +974,12 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize:
when {
identityMismatchRecipientIds.contains(it.recipientId.toLong()) -> {
statusBuilder.failed = SendStatus.Failed(
identityKeyMismatch = true
reason = SendStatus.Failed.FailureReason.IDENTITY_KEY_MISMATCH
)
}
networkFailureRecipientIds.contains(it.recipientId.toLong()) -> {
statusBuilder.failed = SendStatus.Failed(
network = true
reason = SendStatus.Failed.FailureReason.NETWORK
)
}
it.status == GroupReceiptTable.STATUS_UNKNOWN -> {

View File

@@ -69,6 +69,7 @@ import org.thoughtcrime.securesms.payments.CryptoValueUtil
import org.thoughtcrime.securesms.payments.Direction
import org.thoughtcrime.securesms.payments.State
import org.thoughtcrime.securesms.payments.proto.PaymentMetaData
import org.thoughtcrime.securesms.profiles.ProfileName
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.stickers.StickerLocator
@@ -531,7 +532,7 @@ class ChatItemImportInserter(
ReactionTable.MESSAGE_ID to messageId,
ReactionTable.AUTHOR_ID to authorId,
ReactionTable.DATE_SENT to it.sentTimestamp,
ReactionTable.DATE_RECEIVED to (it.receivedTimestamp ?: it.sortOrder),
ReactionTable.DATE_RECEIVED to it.sortOrder,
ReactionTable.EMOJI to it.emoji
)
} else {
@@ -571,9 +572,9 @@ class ChatItemImportInserter(
private fun ChatItem.getMessageType(): Long {
var type: Long = if (this.outgoing != null) {
if (this.outgoing.sendStatus.count { it.failed?.identityKeyMismatch == true } > 0) {
if (this.outgoing.sendStatus.count { it.failed?.reason == SendStatus.Failed.FailureReason.IDENTITY_KEY_MISMATCH } > 0) {
MessageTypes.BASE_SENT_FAILED_TYPE
} else if (this.outgoing.sendStatus.count { it.failed?.network == true } > 0) {
} else if (this.outgoing.sendStatus.count { it.failed?.reason == SendStatus.Failed.FailureReason.NETWORK } > 0) {
MessageTypes.BASE_SENDING_TYPE
} else {
MessageTypes.BASE_SENT_TYPE
@@ -812,10 +813,10 @@ class ChatItemImportInserter(
private fun ContentValues.addQuote(quote: Quote) {
this.put(MessageTable.QUOTE_ID, quote.targetSentTimestamp ?: MessageTable.QUOTE_TARGET_MISSING_ID)
this.put(MessageTable.QUOTE_AUTHOR, importState.remoteToLocalRecipientId[quote.authorId]!!.serialize())
this.put(MessageTable.QUOTE_BODY, quote.text)
this.put(MessageTable.QUOTE_BODY, quote.text?.body)
this.put(MessageTable.QUOTE_TYPE, quote.type.toLocalQuoteType())
this.put(MessageTable.QUOTE_BODY_RANGES, quote.bodyRanges.toLocalBodyRanges()?.encode())
// TODO quote attachments
this.put(MessageTable.QUOTE_BODY_RANGES, quote.text?.bodyRanges?.toLocalBodyRanges()?.encode())
// TODO [backup] quote attachments
this.put(MessageTable.QUOTE_MISSING, (quote.targetSentTimestamp == null).toInt())
}
@@ -842,7 +843,7 @@ class ChatItemImportInserter(
}
val networkFailures = chatItem.outgoing.sendStatus
.filter { status -> status.failed?.network ?: false }
.filter { status -> status.failed?.reason == SendStatus.Failed.FailureReason.NETWORK }
.mapNotNull { status -> importState.remoteToLocalRecipientId[status.recipientId] }
.map { recipientId -> NetworkFailure(recipientId) }
.toSet()
@@ -858,7 +859,7 @@ class ChatItemImportInserter(
}
val mismatches = chatItem.outgoing.sendStatus
.filter { status -> status.failed?.identityKeyMismatch ?: false }
.filter { status -> status.failed?.reason == SendStatus.Failed.FailureReason.IDENTITY_KEY_MISMATCH }
.mapNotNull { status -> importState.remoteToLocalRecipientId[status.recipientId] }
.map { recipientId -> IdentityKeyMismatch(recipientId, null) } // TODO We probably want the actual identity key in this status situation?
.toSet()
@@ -1057,7 +1058,8 @@ class ChatItemImportInserter(
}
private fun ContactAttachment.Name?.toLocal(): Contact.Name {
return Contact.Name(this?.displayName, this?.givenName, this?.familyName, this?.prefix, this?.suffix, this?.middleName)
val displayName = ProfileName.fromParts(this?.givenName, this?.familyName).toString()
return Contact.Name(displayName, this?.givenName, this?.familyName, this?.prefix, this?.suffix, this?.middleName)
}
private fun ContactAttachment.Phone.Type?.toLocal(): Contact.Phone.Type {

View File

@@ -324,11 +324,11 @@ private fun DecryptedGroup.toSnapshot(): Group.GroupSnapshot? {
}
private fun Group.Member.toLocal(): DecryptedMember {
return DecryptedMember(aciBytes = userId, role = role.toLocal(), profileKey = profileKey, joinedAtRevision = joinedAtVersion)
return DecryptedMember(aciBytes = userId, role = role.toLocal(), joinedAtRevision = joinedAtVersion)
}
private fun DecryptedMember.toSnapshot(): Group.Member {
return Group.Member(userId = aciBytes, role = role.toSnapshot(), profileKey = profileKey, joinedAtVersion = joinedAtRevision)
return Group.Member(userId = aciBytes, role = role.toSnapshot(), joinedAtVersion = joinedAtRevision)
}
private fun Group.MemberPendingProfileKey.toLocal(operations: GroupsV2Operations.GroupOperations): DecryptedPendingMember {
@@ -355,7 +355,6 @@ private fun DecryptedPendingMember.toSnapshot(): Group.MemberPendingProfileKey {
private fun Group.MemberPendingAdminApproval.toLocal(): DecryptedRequestingMember {
return DecryptedRequestingMember(
aciBytes = this.userId,
profileKey = this.profileKey,
timestamp = this.timestamp
)
}
@@ -363,7 +362,6 @@ private fun Group.MemberPendingAdminApproval.toLocal(): DecryptedRequestingMembe
private fun DecryptedRequestingMember.toSnapshot(): Group.MemberPendingAdminApproval {
return Group.MemberPendingAdminApproval(
userId = this.aciBytes,
profileKey = this.profileKey,
timestamp = this.timestamp
)
}

View File

@@ -39,6 +39,7 @@ fun ThreadTable.getThreadsForBackup(): ChatExportIterator {
${ThreadTable.READ},
${ThreadTable.ARCHIVED},
${RecipientTable.TABLE_NAME}.${RecipientTable.MESSAGE_EXPIRATION_TIME},
${RecipientTable.TABLE_NAME}.${RecipientTable.MESSAGE_EXPIRATION_TIME_VERSION},
${RecipientTable.TABLE_NAME}.${RecipientTable.MUTE_UNTIL},
${RecipientTable.TABLE_NAME}.${RecipientTable.MENTION_SETTING},
${RecipientTable.TABLE_NAME}.${RecipientTable.CHAT_COLORS},
@@ -73,6 +74,7 @@ fun ThreadTable.restoreFromBackup(chat: Chat, recipientId: RecipientId, importSt
ThreadTable.ACTIVE to 1
)
.run()
writableDatabase
.update(
RecipientTable.TABLE_NAME,
@@ -80,6 +82,7 @@ fun ThreadTable.restoreFromBackup(chat: Chat, recipientId: RecipientId, importSt
RecipientTable.MENTION_SETTING to (if (chat.dontNotifyForMentionsIfMuted) RecipientTable.MentionSetting.DO_NOT_NOTIFY.id else RecipientTable.MentionSetting.ALWAYS_NOTIFY.id),
RecipientTable.MUTE_UNTIL to chat.muteUntilMs,
RecipientTable.MESSAGE_EXPIRATION_TIME to chat.expirationTimerMs,
RecipientTable.MESSAGE_EXPIRATION_TIME_VERSION to chat.expireTimerVersion,
RecipientTable.CHAT_COLORS to chatColor?.serialize()?.encode(),
RecipientTable.CUSTOM_CHAT_COLORS_ID to (chatColor?.id ?: ChatColors.Id.NotSet).longValue
),
@@ -116,6 +119,7 @@ class ChatExportIterator(private val cursor: Cursor) : Iterator<Chat>, Closeable
archived = cursor.requireBoolean(ThreadTable.ARCHIVED),
pinnedOrder = cursor.requireInt(ThreadTable.PINNED),
expirationTimerMs = cursor.requireLong(RecipientTable.MESSAGE_EXPIRATION_TIME),
expireTimerVersion = cursor.requireInt(RecipientTable.MESSAGE_EXPIRATION_TIME_VERSION),
muteUntilMs = cursor.requireLong(RecipientTable.MUTE_UNTIL),
markedUnread = ThreadTable.ReadStatus.deserialize(cursor.requireInt(ThreadTable.READ)) == ThreadTable.ReadStatus.FORCED_UNREAD,
dontNotifyForMentionsIfMuted = RecipientTable.MentionSetting.DO_NOT_NOTIFY.id == cursor.requireInt(RecipientTable.MENTION_SETTING),

View File

@@ -160,7 +160,8 @@ public class Contact implements Parcelable {
@JsonProperty
private final String middleName;
public Name(@JsonProperty("displayName") @Nullable String displayName,
public Name(
@JsonProperty("displayName") @Nullable String displayName,
@JsonProperty("givenName") @Nullable String givenName,
@JsonProperty("familyName") @Nullable String familyName,
@JsonProperty("prefix") @Nullable String prefix,

View File

@@ -3,6 +3,7 @@ syntax = "proto3";
package signal.backup;
option java_package = "org.thoughtcrime.securesms.backup.v2.proto";
option swift_prefix = "BackupProto_";
message BackupInfo {
uint64 version = 1;
@@ -190,8 +191,8 @@ message Group {
bytes userId = 1;
Role role = 2;
bytes profileKey = 3;
reserved /*presentation*/ 4; // The field is deprecated in the context of static group state
reserved /*profileKey*/ 3; // This field is ignored in Backups, in favor of Contact frames for members
reserved /*presentation*/ 4; // This field is deprecated in the context of static group state
uint32 joinedAtVersion = 5;
}
@@ -203,8 +204,8 @@ message Group {
message MemberPendingAdminApproval {
bytes userId = 1;
bytes profileKey = 2;
reserved /*presentation*/ 3; // The field is deprecated in the context of static group state
reserved /*profileKey*/ 2; // This field is ignored in Backups, in favor of Contact frames for members
reserved /*presentation*/ 3; // This field is deprecated in the context of static group state
uint64 timestamp = 4;
}
@@ -242,6 +243,7 @@ message Chat {
bool markedUnread = 7;
bool dontNotifyForMentionsIfMuted = 8;
ChatStyle style = 9;
uint32 expireTimerVersion = 10;
}
/**
@@ -365,10 +367,13 @@ message SendStatus {
message Skipped {}
message Failed {
oneof reason {
bool network = 1;
bool identityKeyMismatch = 2;
enum FailureReason {
UNKNOWN = 0; // A valid value -- could indicate a crash or lack of information
NETWORK = 1;
IDENTITY_KEY_MISMATCH = 2;
}
FailureReason reason = 1;
}
uint64 recipientId = 1;
@@ -471,7 +476,6 @@ message ContactAttachment {
optional string prefix = 3;
optional string suffix = 4;
optional string middleName = 5;
optional string displayName = 6;
}
message Phone {
@@ -646,10 +650,9 @@ message Quote {
optional uint64 targetSentTimestamp = 1; // null if the target message could not be found at time of quote insert
uint64 authorId = 2;
optional string text = 3;
optional Text text = 3;
repeated QuotedAttachment attachments = 4;
repeated BodyRange bodyRanges = 5;
Type type = 6;
Type type = 5;
}
message BodyRange {
@@ -675,11 +678,9 @@ message Reaction {
string emoji = 1;
uint64 authorId = 2;
uint64 sentTimestamp = 3;
// Optional because some clients may not track this data
optional uint64 receivedTimestamp = 4;
// A higher sort order means that a reaction is more recent. Some clients may export this as
// incrementing numbers (e.g. 1, 2, 3), others as timestamps.
uint64 sortOrder = 5;
uint64 sortOrder = 4;
}
message ChatUpdateMessage {
@@ -726,6 +727,7 @@ message IndividualCall {
Direction direction = 3;
State state = 4;
uint64 startedCallTimestamp = 5;
bool read = 6;
}
message GroupCall {
@@ -757,6 +759,7 @@ message GroupCall {
uint64 startedCallTimestamp = 5;
// The time the call ended. 0 indicates an unknown time.
uint64 endedCallTimestamp = 6;
bool read = 7;
}
message SimpleChatUpdate {
@@ -777,7 +780,7 @@ message SimpleChatUpdate {
REPORTED_SPAM = 13;
BLOCKED = 14;
UNBLOCKED = 15;
ACCEPTED = 16;
MESSAGE_REQUEST_ACCEPTED = 16;
}
Type type = 1;
@@ -1064,7 +1067,7 @@ message StickerPack {
message ChatStyle {
message Gradient {
uint32 angle = 1; // degrees
repeated fixed32 colors = 2;
repeated fixed32 colors = 2; // 0xAARRGGBB
repeated float positions = 3; // percent from 0 to 1
}
@@ -1072,7 +1075,7 @@ message ChatStyle {
uint64 id = 1;
oneof color {
fixed32 solid = 2;
fixed32 solid = 2; // 0xAARRGGBB
Gradient gradient = 3;
}
}
@@ -1133,6 +1136,8 @@ message ChatStyle {
oneof wallpaper {
WallpaperPreset wallpaperPreset = 1;
// This `FilePointer` is expected not to contain a `fileName`, `width`,
// `height`, or `caption`.
FilePointer wallpaperPhoto = 2;
}