mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-07-09 15:34:27 +01:00
Add various backup fixes for polls.
This commit is contained in:
committed by
jeffrey-signal
parent
3f5a4ebf7b
commit
47201f4955
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+5
@@ -211,6 +211,11 @@ class ArchiveImportExportTests {
|
||||
runTests { it.startsWith("chat_item_view_once_") }
|
||||
}
|
||||
|
||||
// @Test
|
||||
fun chatItemPoll() {
|
||||
runTests { it.startsWith("chat_item_poll_") }
|
||||
}
|
||||
|
||||
// @Test
|
||||
fun notificationProfiles() {
|
||||
runTests { it.startsWith("notification_profile_") }
|
||||
|
||||
@@ -123,6 +123,14 @@ object ExportSkips {
|
||||
return log(sentTimestamp, "Poll terminate update was empty.")
|
||||
}
|
||||
|
||||
fun invalidPollQuestion(sentTimestamp: Long): String {
|
||||
return log(sentTimestamp, "Poll question was invalid.")
|
||||
}
|
||||
|
||||
fun invalidPollOption(sentTimestamp: Long): String {
|
||||
return log(sentTimestamp, "Poll option was invalid.")
|
||||
}
|
||||
|
||||
fun individualChatUpdateInWrongTypeOfChat(sentTimestamp: Long): String {
|
||||
return log(sentTimestamp, "A chat update that only makes sense for individual chats was found in a different kind of chat.")
|
||||
}
|
||||
|
||||
+15
-4
@@ -117,6 +117,8 @@ private val TAG = Log.tag(ChatItemArchiveExporter::class.java)
|
||||
private val MAX_INLINED_BODY_SIZE = 128.kibiBytes.bytes.toInt()
|
||||
private val MAX_INLINED_BODY_SIZE_WITH_LONG_ATTACHMENT_POINTER = 2.kibiBytes.bytes.toInt()
|
||||
private val MAX_INLINED_QUOTE_BODY_SIZE = 2.kibiBytes.bytes.toInt()
|
||||
private const val MAX_POLL_CHARACTER_LENGTH = 100
|
||||
private const val MAX_POLL_OPTIONS = 10
|
||||
|
||||
/**
|
||||
* An iterator for chat items with a clever performance twist: rather than do the extra queries one at a time (for reactions,
|
||||
@@ -386,7 +388,15 @@ class ChatItemArchiveExporter(
|
||||
|
||||
extraData.pollsById[record.id] != null -> {
|
||||
val poll = extraData.pollsById[record.id]!!
|
||||
builder.poll = poll.toRemotePollMessage()
|
||||
if (poll.question.isEmpty() || poll.question.length > MAX_POLL_CHARACTER_LENGTH) {
|
||||
Log.w(TAG, ExportSkips.invalidPollQuestion(record.dateSent))
|
||||
continue
|
||||
}
|
||||
if (poll.pollOptions.isEmpty() || poll.pollOptions.size > MAX_POLL_OPTIONS || poll.pollOptions.any { it.text.isEmpty() || it.text.length > MAX_POLL_CHARACTER_LENGTH }) {
|
||||
Log.w(TAG, ExportSkips.invalidPollOption(record.dateSent))
|
||||
continue
|
||||
}
|
||||
builder.poll = poll.toRemotePollMessage(reactionRecords = extraData.reactionsById[record.id])
|
||||
transformTimer.emit("poll")
|
||||
}
|
||||
|
||||
@@ -492,7 +502,7 @@ class ChatItemArchiveExporter(
|
||||
|
||||
val pollsFuture = executor.submitTyped {
|
||||
extraDataTimer.timeEvent("polls") {
|
||||
db.pollTable.getPollsForMessages(messageIds)
|
||||
db.pollTable.getPollsForMessages(messageIds = messageIds, includePending = false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1167,7 +1177,7 @@ private fun BackupMessageRecord.toRemoteGiftBadgeUpdate(): BackupGiftBadge? {
|
||||
)
|
||||
}
|
||||
|
||||
private fun PollRecord.toRemotePollMessage(): Poll {
|
||||
private fun PollRecord.toRemotePollMessage(reactionRecords: List<ReactionRecord>?): Poll {
|
||||
return Poll(
|
||||
question = this.question,
|
||||
allowMultiple = this.allowMultipleVotes,
|
||||
@@ -1182,7 +1192,8 @@ private fun PollRecord.toRemotePollMessage(): Poll {
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
reactions = reactionRecords?.toRemote() ?: emptyList()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -693,6 +693,7 @@ class ChatItemArchiveImporter(
|
||||
this.stickerMessage != null -> this.stickerMessage.reactions
|
||||
this.viewOnceMessage != null -> this.viewOnceMessage.reactions
|
||||
this.directStoryReplyMessage != null -> this.directStoryReplyMessage.reactions
|
||||
this.poll != null -> this.poll.reactions
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
|
||||
@@ -607,7 +607,7 @@ class PollTables(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
/**
|
||||
* Maps message ids to its associated poll (if it exists)
|
||||
*/
|
||||
fun getPollsForMessages(messageIds: Collection<Long>): Map<Long, PollRecord> {
|
||||
fun getPollsForMessages(messageIds: Collection<Long>, includePending: Boolean = true): Map<Long, PollRecord> {
|
||||
if (messageIds.isEmpty() || !Recipient.isSelfSet) {
|
||||
return emptyMap()
|
||||
}
|
||||
@@ -625,9 +625,9 @@ class PollTables(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
||||
val (pendingAdds, pendingRemoves) = getPendingVotes(pollId)
|
||||
val pollOptions = getPollOptions(pollId).map { option ->
|
||||
val voters = pollVotes[option.key] ?: emptyList()
|
||||
val voteState = if (pendingAdds.contains(option.key)) {
|
||||
val voteState = if (includePending && pendingAdds.contains(option.key)) {
|
||||
VoteState.PENDING_ADD
|
||||
} else if (pendingRemoves.contains(option.key)) {
|
||||
} else if (includePending && pendingRemoves.contains(option.key)) {
|
||||
VoteState.PENDING_REMOVE
|
||||
} else if (voters.any { it.id == self }) {
|
||||
VoteState.ADDED
|
||||
|
||||
@@ -120,6 +120,8 @@ import kotlin.time.Duration.Companion.seconds
|
||||
object DataMessageProcessor {
|
||||
|
||||
private const val BODY_RANGE_PROCESSING_LIMIT = 250
|
||||
private const val POLL_CHARACTER_LIMIT = 100
|
||||
private const val POLL_OPTIONS_LIMIT = 10
|
||||
|
||||
fun process(
|
||||
context: Context,
|
||||
@@ -1079,6 +1081,16 @@ object DataMessageProcessor {
|
||||
return null
|
||||
}
|
||||
|
||||
if (poll.question == null || poll.question!!.isEmpty() || poll.question!!.length > POLL_CHARACTER_LIMIT) {
|
||||
warn(envelope.timestamp!!, "[handlePollCreate] Poll question is invalid.")
|
||||
return null
|
||||
}
|
||||
|
||||
if (poll.options.isEmpty() || poll.options.size > POLL_OPTIONS_LIMIT || poll.options.any { it.isEmpty() || it.length > POLL_CHARACTER_LIMIT }) {
|
||||
warn(envelope.timestamp!!, "[handlePollCreate] Poll option is invalid.")
|
||||
return null
|
||||
}
|
||||
|
||||
val pollMessage = IncomingMessage(
|
||||
type = MessageType.NORMAL,
|
||||
from = senderRecipient.id,
|
||||
|
||||
@@ -824,6 +824,7 @@ message Poll {
|
||||
bool allowMultiple = 2;
|
||||
repeated PollOption options = 3; // At least two
|
||||
bool hasEnded = 4;
|
||||
repeated Reaction reactions = 5;
|
||||
}
|
||||
|
||||
message ChatUpdateMessage {
|
||||
|
||||
Reference in New Issue
Block a user