mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 04:58:45 +00:00
Update to latest Backup.proto.
This commit is contained in:
@@ -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 -> {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user