Merge IncomingTextMessages into IncomingMessage.
This commit is contained in:
parent
23b696c9cf
commit
6b3f41d675
29 changed files with 410 additions and 1006 deletions
|
@ -10,7 +10,7 @@ import org.signal.core.util.ThreadUtil
|
|||
import org.thoughtcrime.securesms.attachments.PointerAttachment
|
||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivity
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMessage
|
||||
import org.thoughtcrime.securesms.profiles.ProfileName
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
@ -64,7 +64,7 @@ class ConversationItemPreviewer {
|
|||
attachment()
|
||||
}
|
||||
|
||||
val message = IncomingMediaMessage(
|
||||
val message = IncomingMessage(
|
||||
from = other.id,
|
||||
body = body,
|
||||
sentTimeMillis = System.currentTimeMillis(),
|
||||
|
@ -83,7 +83,7 @@ class ConversationItemPreviewer {
|
|||
attachment()
|
||||
}
|
||||
|
||||
val message = IncomingMediaMessage(
|
||||
val message = IncomingMessage(
|
||||
from = other.id,
|
||||
body = body,
|
||||
sentTimeMillis = System.currentTimeMillis(),
|
||||
|
|
|
@ -3,7 +3,7 @@ package org.thoughtcrime.securesms.database
|
|||
import org.thoughtcrime.securesms.database.model.ParentStoryId
|
||||
import org.thoughtcrime.securesms.database.model.StoryType
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMessage
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import java.util.Optional
|
||||
|
@ -55,7 +55,7 @@ object MmsHelper {
|
|||
}
|
||||
|
||||
fun insert(
|
||||
message: IncomingMediaMessage,
|
||||
message: IncomingMessage,
|
||||
threadId: Long
|
||||
): Optional<MessageTable.InsertResult> {
|
||||
return SignalDatabase.messages.insertMessageInbox(message, threadId)
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.thoughtcrime.securesms.database.model.DistributionListId
|
|||
import org.thoughtcrime.securesms.database.model.ParentStoryId
|
||||
import org.thoughtcrime.securesms.database.model.StoryType
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
|
@ -73,7 +73,7 @@ class MmsTableTest_stories {
|
|||
)
|
||||
|
||||
MmsHelper.insert(
|
||||
IncomingMediaMessage(
|
||||
IncomingMessage(
|
||||
from = sender,
|
||||
sentTimeMillis = 2,
|
||||
serverTimeMillis = 2,
|
||||
|
@ -95,7 +95,7 @@ class MmsTableTest_stories {
|
|||
// GIVEN
|
||||
val sender = recipients[0]
|
||||
val messageId = MmsHelper.insert(
|
||||
IncomingMediaMessage(
|
||||
IncomingMessage(
|
||||
from = sender,
|
||||
sentTimeMillis = 2,
|
||||
serverTimeMillis = 2,
|
||||
|
@ -122,7 +122,7 @@ class MmsTableTest_stories {
|
|||
// GIVEN
|
||||
val messageIds = recipients.take(5).map {
|
||||
MmsHelper.insert(
|
||||
IncomingMediaMessage(
|
||||
IncomingMessage(
|
||||
from = it,
|
||||
sentTimeMillis = 2,
|
||||
serverTimeMillis = 2,
|
||||
|
@ -154,7 +154,7 @@ class MmsTableTest_stories {
|
|||
val unviewedIds: List<Long> = (0 until 5).map {
|
||||
Thread.sleep(5)
|
||||
MmsHelper.insert(
|
||||
IncomingMediaMessage(
|
||||
IncomingMessage(
|
||||
from = recipients[it],
|
||||
sentTimeMillis = System.currentTimeMillis(),
|
||||
serverTimeMillis = 2,
|
||||
|
@ -168,7 +168,7 @@ class MmsTableTest_stories {
|
|||
val viewedIds: List<Long> = (0 until 5).map {
|
||||
Thread.sleep(5)
|
||||
MmsHelper.insert(
|
||||
IncomingMediaMessage(
|
||||
IncomingMessage(
|
||||
from = recipients[it],
|
||||
sentTimeMillis = System.currentTimeMillis(),
|
||||
serverTimeMillis = 2,
|
||||
|
@ -213,7 +213,7 @@ class MmsTableTest_stories {
|
|||
fun givenNoOutgoingStories_whenICheckIsOutgoingStoryAlreadyInDatabase_thenIExpectFalse() {
|
||||
// GIVEN
|
||||
MmsHelper.insert(
|
||||
IncomingMediaMessage(
|
||||
IncomingMessage(
|
||||
from = recipients[0],
|
||||
sentTimeMillis = 200,
|
||||
serverTimeMillis = 2,
|
||||
|
@ -321,7 +321,7 @@ class MmsTableTest_stories {
|
|||
)
|
||||
|
||||
MmsHelper.insert(
|
||||
IncomingMediaMessage(
|
||||
IncomingMessage(
|
||||
from = myStory.id,
|
||||
sentTimeMillis = 201,
|
||||
serverTimeMillis = 201,
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.junit.runner.RunWith
|
|||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.SqlUtil
|
||||
import org.signal.core.util.exists
|
||||
import org.signal.core.util.orNull
|
||||
import org.signal.core.util.requireLong
|
||||
import org.signal.core.util.requireNonNullString
|
||||
import org.signal.core.util.select
|
||||
|
@ -35,11 +36,10 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent
|
|||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.thoughtcrime.securesms.util.FeatureFlagsAccessor
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
|
@ -947,12 +947,28 @@ class RecipientTableTest_getAndPossiblyMerge {
|
|||
MatcherAssert.assertThat("Distribution list should have updated $recipientIdE164 to $recipientIdAci", updatedList.members, Matchers.containsInAnyOrder(recipientIdAci, recipientIdAciB))
|
||||
}
|
||||
|
||||
private fun smsMessage(sender: RecipientId, time: Long = 0, body: String = "", groupId: Optional<GroupId> = Optional.empty()): IncomingTextMessage {
|
||||
return IncomingTextMessage(sender, 1, time, time, time, body, groupId, 0, true, null)
|
||||
private fun smsMessage(sender: RecipientId, time: Long = 0, body: String = "", groupId: Optional<GroupId> = Optional.empty()): IncomingMessage {
|
||||
return IncomingMessage(
|
||||
from = sender,
|
||||
sentTimeMillis = time,
|
||||
serverTimeMillis = time,
|
||||
receivedTimeMillis = time,
|
||||
body = body,
|
||||
groupId = groupId.orNull(),
|
||||
isUnidentified = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun mmsMessage(sender: RecipientId, time: Long = 0, body: String = "", groupId: Optional<GroupId> = Optional.empty()): IncomingMediaMessage {
|
||||
return IncomingMediaMessage(sender, groupId, body, time, time, time, emptyList(), 0, 0, false, false, true, Optional.empty(), false, false)
|
||||
private fun mmsMessage(sender: RecipientId, time: Long = 0, body: String = "", groupId: Optional<GroupId> = Optional.empty()): IncomingMessage {
|
||||
return IncomingMessage(
|
||||
from = sender,
|
||||
groupId = groupId.orNull(),
|
||||
body = body,
|
||||
sentTimeMillis = time,
|
||||
receivedTimeMillis = time,
|
||||
serverTimeMillis = time,
|
||||
isUnidentified = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun identityKey(value: Byte): IdentityKey {
|
||||
|
|
|
@ -18,12 +18,10 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.groupChange
|
|||
import org.thoughtcrime.securesms.database.model.databaseprotos.groupContext
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.sms.IncomingGroupUpdateMessage
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
|
||||
@Suppress("ClassName", "TestFunctionName")
|
||||
|
@ -272,13 +270,27 @@ class SmsDatabaseTest_collapseJoinRequestEventsIfPossible {
|
|||
assertThat("latest message should be deleted", sms.getMessageRecordOrNull(latestMessage.messageId), nullValue())
|
||||
}
|
||||
|
||||
private fun smsMessage(sender: RecipientId, body: String? = ""): IncomingTextMessage {
|
||||
private fun smsMessage(sender: RecipientId, body: String? = ""): IncomingMessage {
|
||||
wallClock++
|
||||
return IncomingTextMessage(sender, 1, wallClock, wallClock, wallClock, body, Optional.of(groupId), 0, true, null)
|
||||
return IncomingMessage(
|
||||
from = sender,
|
||||
sentTimeMillis = wallClock,
|
||||
serverTimeMillis = wallClock,
|
||||
receivedTimeMillis = wallClock,
|
||||
body = body,
|
||||
groupId = groupId,
|
||||
isUnidentified = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun groupUpdateMessage(sender: RecipientId, groupContext: DecryptedGroupV2Context): IncomingGroupUpdateMessage {
|
||||
return IncomingGroupUpdateMessage(smsMessage(sender, null), groupContext)
|
||||
private fun groupUpdateMessage(sender: RecipientId, groupContext: DecryptedGroupV2Context): IncomingMessage {
|
||||
wallClock++
|
||||
return IncomingMessage.groupUpdate(
|
||||
from = sender,
|
||||
timestamp = wallClock,
|
||||
groupId = groupId,
|
||||
groupContext = groupContext
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -38,10 +38,8 @@ object MessageTableTestUtils {
|
|||
isKeyExchangeType:${type and MessageTypes.KEY_EXCHANGE_BIT != 0L}
|
||||
isIdentityVerified:${type and MessageTypes.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT != 0L}
|
||||
isIdentityDefault:${type and MessageTypes.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT != 0L}
|
||||
isCorruptedKeyExchange:${type and MessageTypes.KEY_EXCHANGE_CORRUPTED_BIT != 0L}
|
||||
isInvalidVersionKeyExchange:${type and MessageTypes.KEY_EXCHANGE_INVALID_VERSION_BIT != 0L}
|
||||
isBundleKeyExchange:${type and MessageTypes.KEY_EXCHANGE_BUNDLE_BIT != 0L}
|
||||
isContentBundleKeyExchange:${type and MessageTypes.KEY_EXCHANGE_CONTENT_FORMAT != 0L}
|
||||
isIdentityUpdate:${type and MessageTypes.KEY_EXCHANGE_IDENTITY_UPDATE_BIT != 0L}
|
||||
isRateLimited:${type and MessageTypes.MESSAGE_RATE_LIMITED_BIT != 0L}
|
||||
isExpirationTimerUpdate:${type and MessageTypes.EXPIRATION_TIMER_UPDATE_BIT != 0L}
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.database.SignalDatabase
|
|||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.jobs.SyncSystemContactLinksJob
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels
|
||||
import org.thoughtcrime.securesms.notifications.v2.ConversationId
|
||||
import org.thoughtcrime.securesms.permissions.Permissions
|
||||
|
@ -23,7 +24,6 @@ import org.thoughtcrime.securesms.profiles.ProfileName
|
|||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.registration.RegistrationUtil
|
||||
import org.thoughtcrime.securesms.sms.IncomingJoinedMessage
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
|
@ -197,7 +197,7 @@ object ContactDiscovery {
|
|||
|
||||
Recipient.resolvedList(newUserIds)
|
||||
.filter { !it.isSelf && it.hasAUserSetDisplayName(context) && !hasSession(it.id) }
|
||||
.map { IncomingJoinedMessage(it.id) }
|
||||
.map { IncomingMessage.contactJoined(it.id, System.currentTimeMillis()) }
|
||||
.map { SignalDatabase.messages.insertMessageInbox(it) }
|
||||
.filter { it.isPresent }
|
||||
.map { it.get() }
|
||||
|
|
|
@ -56,6 +56,7 @@ import org.signal.core.util.requireLongOrNull
|
|||
import org.signal.core.util.requireNonNullString
|
||||
import org.signal.core.util.requireString
|
||||
import org.signal.core.util.select
|
||||
import org.signal.core.util.toInt
|
||||
import org.signal.core.util.toOptional
|
||||
import org.signal.core.util.toSingleLine
|
||||
import org.signal.core.util.update
|
||||
|
@ -118,7 +119,7 @@ import org.thoughtcrime.securesms.jobs.ThreadUpdateJob
|
|||
import org.thoughtcrime.securesms.jobs.TrimThreadJob
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.mms.MessageGroupContext
|
||||
import org.thoughtcrime.securesms.mms.MmsException
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMessage
|
||||
|
@ -129,8 +130,7 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
|||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo
|
||||
import org.thoughtcrime.securesms.revealable.ViewOnceUtil
|
||||
import org.thoughtcrime.securesms.sms.IncomingGroupUpdateMessage
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage
|
||||
import org.thoughtcrime.securesms.sms.GroupV2UpdateMessageUtil
|
||||
import org.thoughtcrime.securesms.stories.Stories.isFeatureEnabled
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.thoughtcrime.securesms.util.JsonUtils
|
||||
|
@ -591,22 +591,10 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
.run()
|
||||
}
|
||||
|
||||
fun markAsEndSession(id: Long) {
|
||||
updateTypeBitmask(id, MessageTypes.KEY_EXCHANGE_MASK, MessageTypes.END_SESSION_BIT)
|
||||
}
|
||||
|
||||
fun markAsInvalidVersionKeyExchange(id: Long) {
|
||||
updateTypeBitmask(id, 0, MessageTypes.KEY_EXCHANGE_INVALID_VERSION_BIT)
|
||||
}
|
||||
|
||||
fun markAsDecryptFailed(id: Long) {
|
||||
updateTypeBitmask(id, MessageTypes.ENCRYPTION_MASK, MessageTypes.ENCRYPTION_REMOTE_FAILED_BIT)
|
||||
}
|
||||
|
||||
fun markAsNoSession(id: Long) {
|
||||
updateTypeBitmask(id, MessageTypes.ENCRYPTION_MASK, MessageTypes.ENCRYPTION_REMOTE_NO_SESSION_BIT)
|
||||
}
|
||||
|
||||
fun markAsUnsupportedProtocolVersion(id: Long) {
|
||||
updateTypeBitmask(id, MessageTypes.BASE_TYPE_MASK, MessageTypes.UNSUPPORTED_MESSAGE_TYPE)
|
||||
}
|
||||
|
@ -619,10 +607,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
updateTypeBitmask(id, MessageTypes.ENCRYPTION_MASK, MessageTypes.ENCRYPTION_REMOTE_LEGACY_BIT)
|
||||
}
|
||||
|
||||
fun markAsMissedCall(id: Long, isVideoOffer: Boolean) {
|
||||
updateTypeBitmask(id, MessageTypes.TOTAL_MASK, if (isVideoOffer) MessageTypes.MISSED_VIDEO_CALL_TYPE else MessageTypes.MISSED_AUDIO_CALL_TYPE)
|
||||
}
|
||||
|
||||
fun markSmsStatus(id: Long, status: Int) {
|
||||
Log.i(TAG, "Updating ID: $id to status: $status")
|
||||
|
||||
|
@ -982,132 +966,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
}
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun insertMessageInbox(message: IncomingTextMessage, editedMessage: MediaMmsMessageRecord? = null, notifyObservers: Boolean = true): Optional<InsertResult> {
|
||||
var type = MessageTypes.BASE_INBOX_TYPE
|
||||
var tryToCollapseJoinRequestEvents = false
|
||||
|
||||
if (message.isJoined) {
|
||||
type = type and MessageTypes.TOTAL_MASK - MessageTypes.BASE_TYPE_MASK or MessageTypes.JOINED_TYPE
|
||||
} else if (message.isPreKeyBundle) {
|
||||
type = type or (MessageTypes.KEY_EXCHANGE_BIT or MessageTypes.KEY_EXCHANGE_BUNDLE_BIT)
|
||||
} else if (message.isSecureMessage) {
|
||||
type = type or MessageTypes.SECURE_MESSAGE_BIT
|
||||
} else if (message.isGroup) {
|
||||
val incomingGroupUpdateMessage = message as IncomingGroupUpdateMessage
|
||||
type = type or MessageTypes.SECURE_MESSAGE_BIT
|
||||
if (incomingGroupUpdateMessage.isGroupV2) {
|
||||
type = type or (MessageTypes.GROUP_V2_BIT or MessageTypes.GROUP_UPDATE_BIT)
|
||||
if (incomingGroupUpdateMessage.isJustAGroupLeave) {
|
||||
type = type or MessageTypes.GROUP_LEAVE_BIT
|
||||
} else if (incomingGroupUpdateMessage.isCancelJoinRequest) {
|
||||
tryToCollapseJoinRequestEvents = true
|
||||
}
|
||||
} else if (incomingGroupUpdateMessage.isUpdate) {
|
||||
type = type or MessageTypes.GROUP_UPDATE_BIT
|
||||
} else if (incomingGroupUpdateMessage.isQuit) {
|
||||
type = type or MessageTypes.GROUP_LEAVE_BIT
|
||||
}
|
||||
} else if (message.isEndSession) {
|
||||
type = type or MessageTypes.SECURE_MESSAGE_BIT
|
||||
type = type or MessageTypes.END_SESSION_BIT
|
||||
}
|
||||
|
||||
if (message.isPush) {
|
||||
type = type or MessageTypes.PUSH_MESSAGE_BIT
|
||||
}
|
||||
|
||||
if (message.isIdentityUpdate) {
|
||||
type = type or MessageTypes.KEY_EXCHANGE_IDENTITY_UPDATE_BIT
|
||||
}
|
||||
|
||||
if (message.isContentPreKeyBundle) {
|
||||
type = type or MessageTypes.KEY_EXCHANGE_CONTENT_FORMAT
|
||||
}
|
||||
|
||||
if (message.isIdentityVerified) {
|
||||
type = type or MessageTypes.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT
|
||||
} else if (message.isIdentityDefault) {
|
||||
type = type or MessageTypes.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT
|
||||
}
|
||||
|
||||
val silent = message.isIdentityUpdate ||
|
||||
message.isIdentityVerified ||
|
||||
message.isIdentityDefault ||
|
||||
message.isJustAGroupLeave || type and MessageTypes.GROUP_UPDATE_BIT > 0
|
||||
|
||||
val unread = !silent && (
|
||||
message.isSecureMessage ||
|
||||
message.isGroup ||
|
||||
message.isPreKeyBundle ||
|
||||
Util.isDefaultSmsProvider(context)
|
||||
)
|
||||
|
||||
val threadId: Long = if (message.groupId == null) threads.getOrCreateThreadIdFor(message.authorId, false) else threads.getOrCreateThreadIdFor(RecipientId.from(message.groupId!!), true)
|
||||
|
||||
if (tryToCollapseJoinRequestEvents) {
|
||||
val result = collapseJoinRequestEventsIfPossible(threadId, message as IncomingGroupUpdateMessage)
|
||||
if (result.isPresent) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
val values = ContentValues()
|
||||
values.put(FROM_RECIPIENT_ID, message.authorId.serialize())
|
||||
values.put(FROM_DEVICE_ID, message.authorDeviceId)
|
||||
values.put(TO_RECIPIENT_ID, Recipient.self().id.serialize())
|
||||
values.put(DATE_RECEIVED, message.receivedTimestampMillis)
|
||||
values.put(DATE_SENT, message.sentTimestampMillis)
|
||||
values.put(DATE_SERVER, message.serverTimestampMillis)
|
||||
values.put(READ, if (unread) 0 else 1)
|
||||
values.put(SMS_SUBSCRIPTION_ID, message.subscriptionId)
|
||||
values.put(EXPIRES_IN, message.expiresIn)
|
||||
values.put(UNIDENTIFIED, message.isUnidentified)
|
||||
values.put(BODY, message.messageBody)
|
||||
values.put(TYPE, type)
|
||||
values.put(THREAD_ID, threadId)
|
||||
values.put(SERVER_GUID, message.serverGuid)
|
||||
|
||||
if (editedMessage != null) {
|
||||
values.put(ORIGINAL_MESSAGE_ID, editedMessage.getOriginalOrOwnMessageId().id)
|
||||
} else {
|
||||
values.putNull(ORIGINAL_MESSAGE_ID)
|
||||
}
|
||||
|
||||
val messageId: Long = writableDatabase.withinTransaction {
|
||||
val id = writableDatabase.insert(TABLE_NAME, null, values)
|
||||
|
||||
if (id < 0) {
|
||||
Log.w(TAG, "Failed to insert text message (${message.sentTimestampMillis}, ${message.authorId}, ThreadId::$threadId)! Likely a duplicate.")
|
||||
} else {
|
||||
if (unread && editedMessage == null) {
|
||||
threads.incrementUnread(threadId, 1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
id
|
||||
}
|
||||
|
||||
if (messageId < 0) {
|
||||
return Optional.empty()
|
||||
}
|
||||
|
||||
threads.markAsActiveEarly(threadId)
|
||||
|
||||
if (!silent) {
|
||||
ThreadUpdateJob.enqueue(threadId)
|
||||
TrimThreadJob.enqueueAsync(threadId)
|
||||
}
|
||||
|
||||
if (notifyObservers) {
|
||||
notifyConversationListeners(threadId)
|
||||
}
|
||||
|
||||
return Optional.of(InsertResult(messageId, threadId))
|
||||
}
|
||||
|
||||
fun insertEditMessageInbox(threadId: Long, mediaMessage: IncomingMediaMessage, targetMessage: MediaMmsMessageRecord): Optional<InsertResult> {
|
||||
val insertResult = insertMessageInbox(retrieved = mediaMessage, candidateThreadId = threadId, editedMessage = targetMessage, notifyObservers = false)
|
||||
fun insertEditMessageInbox(mediaMessage: IncomingMessage, targetMessage: MediaMmsMessageRecord): Optional<InsertResult> {
|
||||
val insertResult = insertMessageInbox(retrieved = mediaMessage, editedMessage = targetMessage, notifyObservers = false)
|
||||
|
||||
if (insertResult.isPresent) {
|
||||
val (messageId) = insertResult.get()
|
||||
|
@ -1129,29 +989,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
return insertResult
|
||||
}
|
||||
|
||||
fun insertEditMessageInbox(textMessage: IncomingTextMessage, targetMessage: MediaMmsMessageRecord): Optional<InsertResult> {
|
||||
val insertResult = insertMessageInbox(message = textMessage, editedMessage = targetMessage, notifyObservers = false)
|
||||
|
||||
if (insertResult.isPresent) {
|
||||
val (messageId) = insertResult.get()
|
||||
|
||||
if (targetMessage.expireStarted > 0) {
|
||||
markExpireStarted(messageId, targetMessage.expireStarted)
|
||||
}
|
||||
|
||||
writableDatabase.update(TABLE_NAME)
|
||||
.values(LATEST_REVISION_ID to messageId)
|
||||
.where("$ID_WHERE OR $LATEST_REVISION_ID = ?", targetMessage.id, targetMessage.id)
|
||||
.run()
|
||||
|
||||
reactions.moveReactionsToNewMessage(newMessageId = messageId, previousId = targetMessage.id)
|
||||
|
||||
notifyConversationListeners(targetMessage.threadId)
|
||||
}
|
||||
|
||||
return insertResult
|
||||
}
|
||||
|
||||
fun insertProfileNameChangeMessages(recipient: Recipient, newProfileName: String, previousProfileName: String) {
|
||||
writableDatabase.withinTransaction { db ->
|
||||
val groupRecords = groups.getGroupsContainingMember(recipient.id, false)
|
||||
|
@ -1890,13 +1727,13 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
.readToSingleLong(-1)
|
||||
}
|
||||
|
||||
private fun getThreadIdFor(retrieved: IncomingMediaMessage): Long {
|
||||
private fun getThreadIdFor(retrieved: IncomingMessage): Long {
|
||||
return if (retrieved.groupId != null) {
|
||||
val groupRecipientId = recipients.getOrInsertFromPossiblyMigratedGroupId(retrieved.groupId)
|
||||
val groupRecipients = Recipient.resolved(groupRecipientId)
|
||||
threads.getOrCreateThreadIdFor(groupRecipients)
|
||||
} else {
|
||||
val sender = Recipient.resolved(retrieved.from!!)
|
||||
val sender = Recipient.resolved(retrieved.from)
|
||||
threads.getOrCreateThreadIdFor(sender)
|
||||
}
|
||||
}
|
||||
|
@ -2586,8 +2423,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
@JvmOverloads
|
||||
@Throws(MmsException::class)
|
||||
fun insertMessageInbox(
|
||||
retrieved: IncomingMediaMessage,
|
||||
candidateThreadId: Long,
|
||||
retrieved: IncomingMessage,
|
||||
candidateThreadId: Long = -1,
|
||||
editedMessage: MediaMmsMessageRecord? = null,
|
||||
notifyObservers: Boolean = true
|
||||
): Optional<InsertResult> {
|
||||
|
@ -2599,10 +2436,25 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
candidateThreadId
|
||||
}
|
||||
|
||||
if (retrieved.type == MessageType.GROUP_UPDATE && retrieved.groupContext?.let { GroupV2UpdateMessageUtil.isJoinRequestCancel(it) } == true) {
|
||||
val result = collapseJoinRequestEventsIfPossible(threadId, retrieved)
|
||||
if (result.isPresent) {
|
||||
Log.d(TAG, "[insertMessageInbox] Collapsed join request events.")
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
val silent = MessageTypes.isGroupUpdate(type) ||
|
||||
retrieved.type == MessageType.IDENTITY_DEFAULT ||
|
||||
retrieved.type == MessageType.IDENTITY_VERIFIED ||
|
||||
retrieved.type == MessageType.IDENTITY_UPDATE
|
||||
|
||||
val read = silent || retrieved.isExpirationUpdate
|
||||
|
||||
val contentValues = contentValuesOf(
|
||||
DATE_SENT to retrieved.sentTimeMillis,
|
||||
DATE_SERVER to retrieved.serverTimeMillis,
|
||||
FROM_RECIPIENT_ID to retrieved.from!!.serialize(),
|
||||
FROM_RECIPIENT_ID to retrieved.from.serialize(),
|
||||
TO_RECIPIENT_ID to Recipient.self().id.serialize(),
|
||||
TYPE to type,
|
||||
MMS_MESSAGE_TYPE to PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF,
|
||||
|
@ -2614,7 +2466,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
VIEW_ONCE to if (retrieved.isViewOnce) 1 else 0,
|
||||
STORY_TYPE to retrieved.storyType.code,
|
||||
PARENT_STORY_ID to if (retrieved.parentStoryId != null) retrieved.parentStoryId.serialize() else 0,
|
||||
READ to if (MessageTypes.isGroupUpdate(type) || retrieved.isExpirationUpdate) 1 else 0,
|
||||
READ to read.toInt(),
|
||||
UNIDENTIFIED to retrieved.isUnidentified,
|
||||
SERVER_GUID to retrieved.serverGuid,
|
||||
LATEST_REVISION_ID to null,
|
||||
|
@ -2655,7 +2507,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
messageRanges = retrieved.messageRanges,
|
||||
contentValues = contentValues,
|
||||
insertListener = null,
|
||||
updateThread = retrieved.storyType === StoryType.NONE,
|
||||
updateThread = retrieved.storyType === StoryType.NONE && !silent,
|
||||
unarchive = true
|
||||
)
|
||||
|
||||
|
@ -3596,7 +3448,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
}
|
||||
|
||||
@VisibleForTesting
|
||||
fun collapseJoinRequestEventsIfPossible(threadId: Long, message: IncomingGroupUpdateMessage): Optional<InsertResult> {
|
||||
fun collapseJoinRequestEventsIfPossible(threadId: Long, message: IncomingMessage): Optional<InsertResult> {
|
||||
var result: InsertResult? = null
|
||||
|
||||
writableDatabase.withinTransaction { db ->
|
||||
|
@ -3604,21 +3456,22 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
val latestMessage = reader.getNext()
|
||||
|
||||
if (latestMessage != null && latestMessage.isGroupV2) {
|
||||
val changeEditor: Optional<ServiceId> = message.changeEditor
|
||||
val changeEditor: Optional<ServiceId> = message.groupContext?.let { GroupV2UpdateMessageUtil.getChangeEditor(it) } ?: Optional.empty()
|
||||
|
||||
if (changeEditor.isPresent && latestMessage.isGroupV2JoinRequest(changeEditor.get())) {
|
||||
val secondLatestMessage = reader.getNext()
|
||||
|
||||
val id: Long
|
||||
val encodedBody: String
|
||||
val changeRevision: Int = message.groupContext?.let { GroupV2UpdateMessageUtil.getChangeRevision(it) } ?: -1
|
||||
|
||||
if (secondLatestMessage != null && secondLatestMessage.isGroupV2JoinRequest(changeEditor.get())) {
|
||||
id = secondLatestMessage.id
|
||||
encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(secondLatestMessage, message.changeRevision, changeEditor.get().toByteString())
|
||||
encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(secondLatestMessage, changeRevision, changeEditor.get().toByteString())
|
||||
deleteMessage(latestMessage.id)
|
||||
} else {
|
||||
id = latestMessage.id
|
||||
encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(latestMessage, message.changeRevision, changeEditor.get().toByteString())
|
||||
encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(latestMessage, changeRevision, changeEditor.get().toByteString())
|
||||
}
|
||||
|
||||
db.update(TABLE_NAME)
|
||||
|
@ -4827,56 +4680,37 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines the database type bitmask for theh inbound message.
|
||||
* Determines the database type bitmask for the inbound message.
|
||||
*/
|
||||
@Throws(MmsException::class)
|
||||
private fun IncomingMediaMessage.toMessageType(): Long {
|
||||
var type = MessageTypes.BASE_INBOX_TYPE or MessageTypes.SECURE_MESSAGE_BIT
|
||||
var hasSpecialType = false
|
||||
|
||||
if (this.isPushMessage) {
|
||||
type = type or MessageTypes.PUSH_MESSAGE_BIT
|
||||
}
|
||||
|
||||
if (this.isExpirationUpdate) {
|
||||
type = type or MessageTypes.EXPIRATION_TIMER_UPDATE_BIT
|
||||
}
|
||||
|
||||
if (this.isStoryReaction) {
|
||||
type = type or MessageTypes.SPECIAL_TYPE_STORY_REACTION
|
||||
hasSpecialType = true
|
||||
}
|
||||
private fun IncomingMessage.toMessageType(): Long {
|
||||
var type = MessageTypes.BASE_INBOX_TYPE or MessageTypes.SECURE_MESSAGE_BIT or MessageTypes.PUSH_MESSAGE_BIT
|
||||
|
||||
if (this.giftBadge != null) {
|
||||
if (hasSpecialType) {
|
||||
throw MmsException("Cannot insert message with multiple special types.")
|
||||
}
|
||||
type = type or MessageTypes.SPECIAL_TYPE_GIFT_BADGE
|
||||
hasSpecialType = true
|
||||
}
|
||||
|
||||
if (this.isPaymentsNotification) {
|
||||
if (hasSpecialType) {
|
||||
throw MmsException("Cannot insert message with multiple special types.")
|
||||
}
|
||||
type = type or MessageTypes.SPECIAL_TYPE_PAYMENTS_NOTIFICATION
|
||||
hasSpecialType = true
|
||||
}
|
||||
type = type or when (this.type) {
|
||||
MessageType.NORMAL -> 0
|
||||
MessageType.EXPIRATION_UPDATE -> MessageTypes.EXPIRATION_TIMER_UPDATE_BIT
|
||||
MessageType.STORY_REACTION -> MessageTypes.SPECIAL_TYPE_STORY_REACTION
|
||||
MessageType.PAYMENTS_NOTIFICATION -> MessageTypes.SPECIAL_TYPE_PAYMENTS_NOTIFICATION
|
||||
MessageType.ACTIVATE_PAYMENTS_REQUEST -> MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST
|
||||
MessageType.PAYMENTS_ACTIVATED -> MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATED
|
||||
MessageType.CONTACT_JOINED -> MessageTypes.JOINED_TYPE
|
||||
MessageType.IDENTITY_UPDATE -> MessageTypes.KEY_EXCHANGE_IDENTITY_UPDATE_BIT
|
||||
MessageType.IDENTITY_VERIFIED -> MessageTypes.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT
|
||||
MessageType.IDENTITY_DEFAULT -> MessageTypes.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT
|
||||
MessageType.END_SESSION -> MessageTypes.END_SESSION_BIT
|
||||
MessageType.GROUP_UPDATE -> {
|
||||
val isOnlyGroupLeave = this.groupContext?.let { GroupV2UpdateMessageUtil.isJustAGroupLeave(it) } ?: false
|
||||
|
||||
if (this.isActivatePaymentsRequest) {
|
||||
if (hasSpecialType) {
|
||||
throw MmsException("Cannot insert message with multiple special types.")
|
||||
if (isOnlyGroupLeave) {
|
||||
MessageTypes.GROUP_V2_BIT or MessageTypes.GROUP_UPDATE_BIT or MessageTypes.GROUP_LEAVE_BIT
|
||||
} else {
|
||||
MessageTypes.GROUP_V2_BIT or MessageTypes.GROUP_UPDATE_BIT
|
||||
}
|
||||
}
|
||||
type = type or MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST
|
||||
hasSpecialType = true
|
||||
}
|
||||
|
||||
if (this.isPaymentsActivated) {
|
||||
if (hasSpecialType) {
|
||||
throw MmsException("Cannot insert message with multiple special types.")
|
||||
}
|
||||
type = type or MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATED
|
||||
hasSpecialType = true
|
||||
}
|
||||
|
||||
return type
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.database
|
||||
|
||||
/**
|
||||
* Describes what type of message something is. This serves as an abstraction layer over the bitmasks
|
||||
* in [MessageTypes]. Currently only used for [org.thoughtcrime.securesms.mms.IncomingMessage],
|
||||
* but will hopefully be used more widely in the future.
|
||||
*/
|
||||
enum class MessageType {
|
||||
/** A typical message with no special typing */
|
||||
NORMAL,
|
||||
|
||||
/** A mobilecoin payment */
|
||||
PAYMENTS_NOTIFICATION,
|
||||
|
||||
/** A request to activate mobilecoin payments */
|
||||
ACTIVATE_PAYMENTS_REQUEST,
|
||||
|
||||
/** Mobilecoin payments have been activated (in response to a [ACTIVATE_PAYMENTS_REQUEST] */
|
||||
PAYMENTS_ACTIVATED,
|
||||
|
||||
/** An emoji reaction to a story */
|
||||
STORY_REACTION,
|
||||
|
||||
/** The chat's expiration timer has been updated */
|
||||
EXPIRATION_UPDATE,
|
||||
|
||||
/** A new contact has joined Signal */
|
||||
CONTACT_JOINED,
|
||||
|
||||
/** Any update to a group */
|
||||
GROUP_UPDATE,
|
||||
|
||||
/** A user's identity/safety number has changed */
|
||||
IDENTITY_UPDATE,
|
||||
|
||||
/** You verified a user's identity/safety number */
|
||||
IDENTITY_VERIFIED,
|
||||
|
||||
/** You unverified a user's identity/safety number, resetting it to the default state */
|
||||
IDENTITY_DEFAULT,
|
||||
|
||||
/** A manual session reset. This is no longer used and is only here for handling possible inbound/sync messages. */
|
||||
END_SESSION
|
||||
}
|
|
@ -78,11 +78,11 @@ public interface MessageTypes {
|
|||
long KEY_EXCHANGE_BIT = 0x8000;
|
||||
long KEY_EXCHANGE_IDENTITY_VERIFIED_BIT = 0x4000;
|
||||
long KEY_EXCHANGE_IDENTITY_DEFAULT_BIT = 0x2000;
|
||||
long KEY_EXCHANGE_CORRUPTED_BIT = 0x1000;
|
||||
// long KEY_EXCHANGE_CORRUPTED_BIT = 0x1000;
|
||||
long KEY_EXCHANGE_INVALID_VERSION_BIT = 0x800;
|
||||
long KEY_EXCHANGE_BUNDLE_BIT = 0x400;
|
||||
long KEY_EXCHANGE_IDENTITY_UPDATE_BIT = 0x200;
|
||||
long KEY_EXCHANGE_CONTENT_FORMAT = 0x100;
|
||||
// long KEY_EXCHANGE_CONTENT_FORMAT = 0x100;
|
||||
|
||||
// Secure Message Information
|
||||
long SECURE_MESSAGE_BIT = 0x800000;
|
||||
|
@ -236,10 +236,6 @@ public interface MessageTypes {
|
|||
return (type & KEY_EXCHANGE_IDENTITY_DEFAULT_BIT) != 0;
|
||||
}
|
||||
|
||||
static boolean isCorruptedKeyExchange(long type) {
|
||||
return (type & KEY_EXCHANGE_CORRUPTED_BIT) != 0;
|
||||
}
|
||||
|
||||
static boolean isInvalidVersionKeyExchange(long type) {
|
||||
return (type & KEY_EXCHANGE_INVALID_VERSION_BIT) != 0;
|
||||
}
|
||||
|
@ -248,10 +244,6 @@ public interface MessageTypes {
|
|||
return (type & KEY_EXCHANGE_BUNDLE_BIT) != 0;
|
||||
}
|
||||
|
||||
static boolean isContentBundleKeyExchange(long type) {
|
||||
return (type & KEY_EXCHANGE_CONTENT_FORMAT) != 0;
|
||||
}
|
||||
|
||||
static boolean isIdentityUpdate(long type) {
|
||||
return (type & KEY_EXCHANGE_IDENTITY_UPDATE_BIT) != 0;
|
||||
}
|
||||
|
|
|
@ -39,12 +39,11 @@ import org.thoughtcrime.securesms.jobs.LeaveGroupV2Job;
|
|||
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob;
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMessage;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.sms.IncomingGroupUpdateMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupHistoryEntry;
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct;
|
||||
|
@ -801,19 +800,22 @@ public class GroupsV2StateProcessor {
|
|||
mmsDatabase.markAsSent(messageId, true);
|
||||
threadTable.update(threadId, false, false);
|
||||
} catch (MmsException e) {
|
||||
Log.w(TAG, e);
|
||||
Log.w(TAG, "Failed to insert outgoing update message!", e);
|
||||
}
|
||||
} else {
|
||||
MessageTable smsDatabase = SignalDatabase.messages();
|
||||
RecipientId sender = RecipientId.from(editor.get());
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(sender, -1, timestamp, timestamp, timestamp, "", Optional.of(groupId), 0, false, null);
|
||||
IncomingGroupUpdateMessage groupMessage = new IncomingGroupUpdateMessage(incoming, decryptedGroupV2Context);
|
||||
Optional<MessageTable.InsertResult> insertResult = smsDatabase.insertMessageInbox(groupMessage);
|
||||
try {
|
||||
MessageTable smsDatabase = SignalDatabase.messages();
|
||||
RecipientId sender = RecipientId.from(editor.get());
|
||||
IncomingMessage groupMessage = IncomingMessage.groupUpdate(sender, timestamp, groupId, decryptedGroupV2Context);
|
||||
Optional<MessageTable.InsertResult> insertResult = smsDatabase.insertMessageInbox(groupMessage);
|
||||
|
||||
if (insertResult.isPresent()) {
|
||||
SignalDatabase.threads().update(insertResult.get().getThreadId(), false, false);
|
||||
} else {
|
||||
Log.w(TAG, "Could not insert update message");
|
||||
if (insertResult.isPresent()) {
|
||||
SignalDatabase.threads().update(insertResult.get().getThreadId(), false, false);
|
||||
} else {
|
||||
Log.w(TAG, "Could not insert update message");
|
||||
}
|
||||
} catch (MmsException e) {
|
||||
Log.w(TAG, "Failed to insert incoming update message!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
|||
import org.thoughtcrime.securesms.crypto.SecurityEvent
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||
import org.thoughtcrime.securesms.database.MessageTable.InsertResult
|
||||
import org.thoughtcrime.securesms.database.MessageType
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException
|
||||
import org.thoughtcrime.securesms.database.PaymentTable.PublicKeyConflictException
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
|
@ -75,7 +76,7 @@ import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isPaymentActiv
|
|||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isStoryReaction
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toPointer
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toPointersWithinLimit
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.mms.MmsException
|
||||
import org.thoughtcrime.securesms.mms.QuoteModel
|
||||
import org.thoughtcrime.securesms.mms.StickerSlide
|
||||
|
@ -84,9 +85,6 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
|||
import org.thoughtcrime.securesms.recipients.Recipient.HiddenState
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil
|
||||
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage
|
||||
import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage
|
||||
import org.thoughtcrime.securesms.stickers.StickerLocator
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry
|
||||
|
@ -100,7 +98,7 @@ import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata
|
|||
import org.whispersystems.signalservice.api.payments.Money
|
||||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.util.OptionalUtil.asOptional
|
||||
import org.whispersystems.signalservice.api.util.Preconditions
|
||||
import org.whispersystems.signalservice.internal.push.BodyRange
|
||||
import org.whispersystems.signalservice.internal.push.Content
|
||||
import org.whispersystems.signalservice.internal.push.DataMessage
|
||||
|
@ -143,7 +141,7 @@ object DataMessageProcessor {
|
|||
|
||||
var messageId: MessageId? = null
|
||||
when {
|
||||
message.isInvalid -> handleInvalidMessage(context, senderRecipient.id, metadata.sourceDeviceId, groupId, envelope.timestamp!!)
|
||||
message.isInvalid -> handleInvalidMessage(context, senderRecipient.id, groupId, envelope.timestamp!!)
|
||||
message.isEndSession -> messageId = handleEndSessionMessage(context, senderRecipient.id, envelope, metadata)
|
||||
message.isExpirationUpdate -> messageId = handleExpirationUpdate(envelope, metadata, senderRecipient.id, threadRecipient.id, groupId, message.expireTimerDuration, receivedTime, false)
|
||||
message.isStoryReaction -> messageId = handleStoryReaction(context, envelope, metadata, message, senderRecipient.id, groupId)
|
||||
|
@ -244,13 +242,12 @@ object DataMessageProcessor {
|
|||
private fun handleInvalidMessage(
|
||||
context: Context,
|
||||
sender: RecipientId,
|
||||
senderDevice: Int,
|
||||
groupId: GroupId?,
|
||||
timestamp: Long
|
||||
) {
|
||||
log(timestamp, "Invalid message.")
|
||||
|
||||
val insertResult: InsertResult? = insertPlaceholder(sender, senderDevice, timestamp, groupId)
|
||||
val insertResult: InsertResult? = insertPlaceholder(sender, timestamp, groupId)
|
||||
if (insertResult != null) {
|
||||
SignalDatabase.messages.markAsInvalidMessage(insertResult.messageId)
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context, ConversationId.forConversation(insertResult.threadId))
|
||||
|
@ -265,20 +262,17 @@ object DataMessageProcessor {
|
|||
): MessageId? {
|
||||
log(envelope.timestamp!!, "End session message.")
|
||||
|
||||
val incomingTextMessage = IncomingTextMessage(
|
||||
senderRecipientId,
|
||||
metadata.sourceDeviceId,
|
||||
envelope.timestamp!!,
|
||||
envelope.serverTimestamp!!,
|
||||
System.currentTimeMillis(),
|
||||
"",
|
||||
Optional.empty(),
|
||||
0,
|
||||
metadata.sealedSender,
|
||||
envelope.serverGuid
|
||||
val incomingMessage = IncomingMessage(
|
||||
from = senderRecipientId,
|
||||
sentTimeMillis = envelope.timestamp!!,
|
||||
serverTimeMillis = envelope.serverTimestamp!!,
|
||||
receivedTimeMillis = System.currentTimeMillis(),
|
||||
isUnidentified = metadata.sealedSender,
|
||||
serverGuid = envelope.serverGuid,
|
||||
type = MessageType.END_SESSION
|
||||
)
|
||||
|
||||
val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(IncomingEndSessionMessage(incomingTextMessage)).orNull()
|
||||
val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(incomingMessage).orNull()
|
||||
|
||||
return if (insertResult != null) {
|
||||
ApplicationDependencies.getProtocolStore().aci().deleteAllSessions(metadata.sourceServiceId.toString())
|
||||
|
@ -318,7 +312,7 @@ object DataMessageProcessor {
|
|||
}
|
||||
|
||||
try {
|
||||
val mediaMessage = IncomingMediaMessage(
|
||||
val mediaMessage = IncomingMessage(
|
||||
from = senderRecipientId,
|
||||
sentTimeMillis = envelope.timestamp!! - if (sideEffect) 1 else 0,
|
||||
serverTimeMillis = envelope.serverTimestamp!!,
|
||||
|
@ -418,7 +412,7 @@ object DataMessageProcessor {
|
|||
return null
|
||||
}
|
||||
|
||||
val mediaMessage = IncomingMediaMessage(
|
||||
val mediaMessage = IncomingMessage(
|
||||
from = senderRecipientId,
|
||||
sentTimeMillis = envelope.timestamp!!,
|
||||
serverTimeMillis = envelope.serverTimestamp!!,
|
||||
|
@ -582,8 +576,10 @@ object DataMessageProcessor {
|
|||
isPaymentsActivated: Boolean
|
||||
): MessageId? {
|
||||
log(envelope.timestamp!!, "Payment activation request: $isActivatePaymentsRequest activated: $isPaymentsActivated")
|
||||
Preconditions.checkArgument(isActivatePaymentsRequest || isPaymentsActivated)
|
||||
|
||||
try {
|
||||
val mediaMessage = IncomingMediaMessage(
|
||||
val mediaMessage = IncomingMessage(
|
||||
from = senderRecipientId,
|
||||
sentTimeMillis = envelope.timestamp!!,
|
||||
serverTimeMillis = envelope.serverTimestamp!!,
|
||||
|
@ -591,8 +587,7 @@ object DataMessageProcessor {
|
|||
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
||||
isUnidentified = metadata.sealedSender,
|
||||
serverGuid = envelope.serverGuid,
|
||||
isActivatePaymentsRequest = isActivatePaymentsRequest,
|
||||
isPaymentsActivated = isPaymentsActivated
|
||||
type = if (isActivatePaymentsRequest) MessageType.ACTIVATE_PAYMENTS_REQUEST else MessageType.PAYMENTS_ACTIVATED
|
||||
)
|
||||
|
||||
val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(mediaMessage, -1).orNull()
|
||||
|
@ -638,7 +633,7 @@ object DataMessageProcessor {
|
|||
true
|
||||
)
|
||||
|
||||
val mediaMessage = IncomingMediaMessage(
|
||||
val mediaMessage = IncomingMessage(
|
||||
from = senderRecipientId,
|
||||
body = uuid.toString(),
|
||||
sentTimeMillis = envelope.timestamp!!,
|
||||
|
@ -648,7 +643,7 @@ object DataMessageProcessor {
|
|||
isUnidentified = metadata.sealedSender,
|
||||
serverGuid = envelope.serverGuid,
|
||||
isPushMessage = true,
|
||||
isPaymentsNotification = true
|
||||
type = MessageType.PAYMENTS_NOTIFICATION
|
||||
)
|
||||
|
||||
val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(mediaMessage, -1).orNull()
|
||||
|
@ -750,7 +745,7 @@ object DataMessageProcessor {
|
|||
|
||||
val bodyRanges: BodyRangeList? = message.bodyRanges.filter { it.mentionAci == null }.toList().toBodyRangeList()
|
||||
|
||||
val mediaMessage = IncomingMediaMessage(
|
||||
val mediaMessage = IncomingMessage(
|
||||
from = senderRecipient.id,
|
||||
sentTimeMillis = envelope.timestamp!!,
|
||||
serverTimeMillis = envelope.serverTimestamp!!,
|
||||
|
@ -818,7 +813,7 @@ object DataMessageProcessor {
|
|||
.build()
|
||||
|
||||
val insertResult: InsertResult? = try {
|
||||
val mediaMessage = IncomingMediaMessage(
|
||||
val mediaMessage = IncomingMessage(
|
||||
from = senderRecipient.id,
|
||||
sentTimeMillis = envelope.timestamp!!,
|
||||
serverTimeMillis = envelope.serverTimestamp!!,
|
||||
|
@ -874,7 +869,7 @@ object DataMessageProcessor {
|
|||
|
||||
handlePossibleExpirationUpdate(envelope, metadata, senderRecipient.id, threadRecipient, groupId, message.expireTimerDuration, receivedTime)
|
||||
|
||||
val mediaMessage = IncomingMediaMessage(
|
||||
val mediaMessage = IncomingMessage(
|
||||
from = senderRecipient.id,
|
||||
sentTimeMillis = envelope.timestamp!!,
|
||||
serverTimeMillis = envelope.serverTimestamp!!,
|
||||
|
@ -956,20 +951,19 @@ object DataMessageProcessor {
|
|||
|
||||
notifyTypingStoppedFromIncomingMessage(context, senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
|
||||
|
||||
val textMessage = IncomingTextMessage(
|
||||
senderRecipient.id,
|
||||
metadata.sourceDeviceId,
|
||||
envelope.timestamp!!,
|
||||
envelope.serverTimestamp!!,
|
||||
receivedTime,
|
||||
body,
|
||||
Optional.ofNullable(groupId),
|
||||
message.expireTimerDuration.inWholeMilliseconds,
|
||||
metadata.sealedSender,
|
||||
envelope.serverGuid
|
||||
val textMessage = IncomingMessage(
|
||||
from = senderRecipient.id,
|
||||
sentTimeMillis = envelope.timestamp!!,
|
||||
serverTimeMillis = envelope.serverTimestamp!!,
|
||||
receivedTimeMillis = receivedTime,
|
||||
body = body,
|
||||
groupId = groupId,
|
||||
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
||||
isUnidentified = metadata.sealedSender,
|
||||
serverGuid = envelope.serverGuid
|
||||
)
|
||||
|
||||
val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(IncomingEncryptedMessage(textMessage, body)).orNull()
|
||||
val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(textMessage).orNull()
|
||||
localMetrics?.onInsertedTextMessage()
|
||||
|
||||
return if (insertResult != null) {
|
||||
|
@ -1031,20 +1025,17 @@ object DataMessageProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
private fun insertPlaceholder(sender: RecipientId, senderDevice: Int, timestamp: Long, groupId: GroupId?): InsertResult? {
|
||||
val textMessage = IncomingTextMessage(
|
||||
sender,
|
||||
senderDevice,
|
||||
timestamp,
|
||||
-1,
|
||||
System.currentTimeMillis(),
|
||||
"",
|
||||
groupId.asOptional(),
|
||||
0,
|
||||
false,
|
||||
null
|
||||
private fun insertPlaceholder(sender: RecipientId, timestamp: Long, groupId: GroupId?): InsertResult? {
|
||||
val textMessage = IncomingMessage(
|
||||
from = sender,
|
||||
sentTimeMillis = timestamp,
|
||||
serverTimeMillis = -1,
|
||||
receivedTimeMillis = System.currentTimeMillis(),
|
||||
body = "",
|
||||
groupId = groupId
|
||||
)
|
||||
return SignalDatabase.messages.insertMessageInbox(IncomingEncryptedMessage(textMessage, "")).orNull()
|
||||
|
||||
return SignalDatabase.messages.insertMessageInbox(textMessage).orNull()
|
||||
}
|
||||
|
||||
fun getValidatedQuote(context: Context, timestamp: Long, message: DataMessage): QuoteModel? {
|
||||
|
|
|
@ -19,13 +19,11 @@ import org.thoughtcrime.securesms.messages.MessageContentProcessor.Companion.war
|
|||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.groupId
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isMediaMessage
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toPointersWithinLimit
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.mms.QuoteModel
|
||||
import org.thoughtcrime.securesms.notifications.v2.ConversationId.Companion.forConversation
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage
|
||||
import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.MessageConstraintsUtil
|
||||
|
@ -35,7 +33,6 @@ import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata
|
|||
import org.whispersystems.signalservice.internal.push.Content
|
||||
import org.whispersystems.signalservice.internal.push.DataMessage
|
||||
import org.whispersystems.signalservice.internal.push.Envelope
|
||||
import java.util.Optional
|
||||
|
||||
object EditMessageProcessor {
|
||||
fun process(
|
||||
|
@ -142,7 +139,7 @@ object EditMessageProcessor {
|
|||
attachments.filter {
|
||||
MediaUtil.SlideType.LONG_TEXT == MediaUtil.getSlideTypeFromContentType(it.contentType)
|
||||
}
|
||||
val mediaMessage = IncomingMediaMessage(
|
||||
val mediaMessage = IncomingMessage(
|
||||
from = senderRecipientId,
|
||||
sentTimeMillis = message.timestamp!!,
|
||||
serverTimeMillis = envelope.serverTimestamp!!,
|
||||
|
@ -162,7 +159,7 @@ object EditMessageProcessor {
|
|||
isPushMessage = true
|
||||
)
|
||||
|
||||
val insertResult = SignalDatabase.messages.insertEditMessageInbox(-1, mediaMessage, targetMessage).orNull()
|
||||
val insertResult = SignalDatabase.messages.insertEditMessageInbox(mediaMessage, targetMessage).orNull()
|
||||
if (insertResult?.insertedAttachments != null) {
|
||||
SignalDatabase.runPostSuccessfulTransaction {
|
||||
val downloadJobs: List<AttachmentDownloadJob> = insertResult.insertedAttachments.mapNotNull { (_, attachmentId) ->
|
||||
|
@ -182,21 +179,18 @@ object EditMessageProcessor {
|
|||
message: DataMessage,
|
||||
targetMessage: MediaMmsMessageRecord
|
||||
): InsertResult? {
|
||||
var textMessage = IncomingTextMessage(
|
||||
senderRecipientId,
|
||||
metadata.sourceDeviceId,
|
||||
envelope.timestamp!!,
|
||||
envelope.timestamp!!,
|
||||
targetMessage.dateReceived,
|
||||
message.body,
|
||||
Optional.ofNullable(groupId),
|
||||
targetMessage.expiresIn,
|
||||
metadata.sealedSender,
|
||||
envelope.serverGuid
|
||||
val textMessage = IncomingMessage(
|
||||
from = senderRecipientId,
|
||||
sentTimeMillis = envelope.timestamp!!,
|
||||
serverTimeMillis = envelope.timestamp!!,
|
||||
receivedTimeMillis = targetMessage.dateReceived,
|
||||
body = message.body,
|
||||
groupId = groupId,
|
||||
expiresIn = targetMessage.expiresIn,
|
||||
isUnidentified = metadata.sealedSender,
|
||||
serverGuid = envelope.serverGuid
|
||||
)
|
||||
|
||||
textMessage = IncomingEncryptedMessage(textMessage, message.body)
|
||||
|
||||
return SignalDatabase.messages.insertEditMessageInbox(textMessage, targetMessage).orNull()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,11 +37,10 @@ import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isMediaMessage
|
|||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isValid
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.signedGroupChange
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toDecryptionErrorMessage
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.notifications.v2.ConversationId
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage
|
||||
import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.thoughtcrime.securesms.util.SignalLocalMetrics
|
||||
|
@ -295,23 +294,18 @@ open class MessageContentProcessor(private val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
private fun insertErrorMessage(context: Context, sender: Recipient, senderDevice: Int, timestamp: Long, groupId: Optional<GroupId>, marker: (Long) -> Unit) {
|
||||
val textMessage = IncomingTextMessage(
|
||||
sender.id,
|
||||
senderDevice,
|
||||
timestamp,
|
||||
-1,
|
||||
System.currentTimeMillis(),
|
||||
"",
|
||||
groupId,
|
||||
0,
|
||||
false,
|
||||
null
|
||||
private fun insertErrorMessage(context: Context, sender: Recipient, timestamp: Long, groupId: Optional<GroupId>, marker: (Long) -> Unit) {
|
||||
val textMessage = IncomingMessage(
|
||||
from = sender.id,
|
||||
sentTimeMillis = timestamp,
|
||||
serverTimeMillis = -1,
|
||||
receivedTimeMillis = System.currentTimeMillis(),
|
||||
groupId = groupId.orNull()
|
||||
)
|
||||
|
||||
SignalDatabase
|
||||
.messages
|
||||
.insertMessageInbox(IncomingEncryptedMessage(textMessage, ""))
|
||||
.insertMessageInbox(textMessage)
|
||||
.ifPresent {
|
||||
marker(it.messageId)
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context, ConversationId.forConversation(it.threadId))
|
||||
|
@ -374,21 +368,21 @@ open class MessageContentProcessor(private val context: Context) {
|
|||
|
||||
MessageState.INVALID_VERSION -> {
|
||||
warn(timestamp, "Handling invalid version.")
|
||||
insertErrorMessage(context, sender, exceptionMetadata.senderDevice, timestamp, exceptionMetadata.groupId.toOptional()) { messageId ->
|
||||
insertErrorMessage(context, sender, timestamp, exceptionMetadata.groupId.toOptional()) { messageId ->
|
||||
SignalDatabase.messages.markAsInvalidVersionKeyExchange(messageId)
|
||||
}
|
||||
}
|
||||
|
||||
MessageState.LEGACY_MESSAGE -> {
|
||||
warn(timestamp, "Handling legacy message.")
|
||||
insertErrorMessage(context, sender, exceptionMetadata.senderDevice, timestamp, exceptionMetadata.groupId.toOptional()) { messageId ->
|
||||
insertErrorMessage(context, sender, timestamp, exceptionMetadata.groupId.toOptional()) { messageId ->
|
||||
SignalDatabase.messages.markAsLegacyVersion(messageId)
|
||||
}
|
||||
}
|
||||
|
||||
MessageState.UNSUPPORTED_DATA_MESSAGE -> {
|
||||
warn(timestamp, "Handling unsupported data message.")
|
||||
insertErrorMessage(context, sender, exceptionMetadata.senderDevice, timestamp, exceptionMetadata.groupId.toOptional()) { messageId ->
|
||||
insertErrorMessage(context, sender, timestamp, exceptionMetadata.groupId.toOptional()) { messageId ->
|
||||
SignalDatabase.messages.markAsUnsupportedProtocolVersion(messageId)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import org.thoughtcrime.securesms.messages.MessageContentProcessor.Companion.log
|
|||
import org.thoughtcrime.securesms.messages.MessageContentProcessor.Companion.warn
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.groupId
|
||||
import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toPointer
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.mms.MmsException
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
|
@ -58,7 +58,7 @@ object StoryMessageProcessor {
|
|||
StoryType.withoutReplies(isTextStory = storyMessage.textAttachment != null)
|
||||
}
|
||||
|
||||
val mediaMessage = IncomingMediaMessage(
|
||||
val mediaMessage = IncomingMessage(
|
||||
from = senderRecipient.id,
|
||||
sentTimeMillis = envelope.timestamp!!,
|
||||
serverTimeMillis = envelope.serverTimestamp!!,
|
||||
|
|
|
@ -1,145 +0,0 @@
|
|||
package org.thoughtcrime.securesms.mms
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.Attachment
|
||||
import org.thoughtcrime.securesms.attachments.PointerAttachment
|
||||
import org.thoughtcrime.securesms.contactshare.Contact
|
||||
import org.thoughtcrime.securesms.database.model.Mention
|
||||
import org.thoughtcrime.securesms.database.model.ParentStoryId
|
||||
import org.thoughtcrime.securesms.database.model.StoryType
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2
|
||||
import java.util.Optional
|
||||
|
||||
class IncomingMediaMessage(
|
||||
val from: RecipientId?,
|
||||
val groupId: GroupId? = null,
|
||||
val body: String? = null,
|
||||
val isPushMessage: Boolean = false,
|
||||
val storyType: StoryType = StoryType.NONE,
|
||||
val parentStoryId: ParentStoryId? = null,
|
||||
val isStoryReaction: Boolean = false,
|
||||
val sentTimeMillis: Long,
|
||||
val serverTimeMillis: Long,
|
||||
val receivedTimeMillis: Long,
|
||||
val subscriptionId: Int = -1,
|
||||
val expiresIn: Long = 0,
|
||||
val isExpirationUpdate: Boolean = false,
|
||||
val quote: QuoteModel? = null,
|
||||
val isUnidentified: Boolean = false,
|
||||
val isViewOnce: Boolean = false,
|
||||
val serverGuid: String? = null,
|
||||
val messageRanges: BodyRangeList? = null,
|
||||
attachments: List<Attachment> = emptyList(),
|
||||
sharedContacts: List<Contact> = emptyList(),
|
||||
linkPreviews: List<LinkPreview> = emptyList(),
|
||||
mentions: List<Mention> = emptyList(),
|
||||
val giftBadge: GiftBadge? = null,
|
||||
val isPaymentsNotification: Boolean = false,
|
||||
val isActivatePaymentsRequest: Boolean = false,
|
||||
val isPaymentsActivated: Boolean = false
|
||||
) {
|
||||
|
||||
val attachments: List<Attachment> = ArrayList(attachments)
|
||||
val sharedContacts: List<Contact> = ArrayList(sharedContacts)
|
||||
val linkPreviews: List<LinkPreview> = ArrayList(linkPreviews)
|
||||
val mentions: List<Mention> = ArrayList(mentions)
|
||||
|
||||
val isGroupMessage: Boolean = groupId != null
|
||||
|
||||
constructor(
|
||||
from: RecipientId?,
|
||||
groupId: Optional<GroupId>,
|
||||
body: String?,
|
||||
sentTimeMillis: Long,
|
||||
serverTimeMillis: Long,
|
||||
receivedTimeMillis: Long,
|
||||
attachments: List<Attachment>?,
|
||||
subscriptionId: Int,
|
||||
expiresIn: Long,
|
||||
expirationUpdate: Boolean,
|
||||
viewOnce: Boolean,
|
||||
unidentified: Boolean,
|
||||
sharedContacts: Optional<List<Contact>>,
|
||||
activatePaymentsRequest: Boolean,
|
||||
paymentsActivated: Boolean
|
||||
) : this(
|
||||
from = from,
|
||||
groupId = groupId.orElse(null),
|
||||
body = body,
|
||||
isPushMessage = false,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
serverTimeMillis = serverTimeMillis,
|
||||
receivedTimeMillis = receivedTimeMillis,
|
||||
subscriptionId = subscriptionId,
|
||||
expiresIn = expiresIn,
|
||||
isExpirationUpdate = expirationUpdate,
|
||||
quote = null,
|
||||
isUnidentified = unidentified,
|
||||
isViewOnce = viewOnce,
|
||||
serverGuid = null,
|
||||
attachments = attachments?.let { ArrayList<Attachment>(it) } ?: emptyList(),
|
||||
sharedContacts = ArrayList<Contact>(sharedContacts.orElse(emptyList())),
|
||||
isActivatePaymentsRequest = activatePaymentsRequest,
|
||||
isPaymentsActivated = paymentsActivated
|
||||
)
|
||||
|
||||
@JvmOverloads
|
||||
constructor(
|
||||
from: RecipientId?,
|
||||
sentTimeMillis: Long,
|
||||
serverTimeMillis: Long,
|
||||
receivedTimeMillis: Long,
|
||||
storyType: StoryType,
|
||||
parentStoryId: ParentStoryId?,
|
||||
isStoryReaction: Boolean,
|
||||
subscriptionId: Int,
|
||||
expiresIn: Long,
|
||||
expirationUpdate: Boolean,
|
||||
viewOnce: Boolean,
|
||||
unidentified: Boolean,
|
||||
body: Optional<String>,
|
||||
group: Optional<SignalServiceGroupV2>,
|
||||
attachments: Optional<List<SignalServiceAttachment>>,
|
||||
quote: Optional<QuoteModel>,
|
||||
sharedContacts: Optional<List<Contact>>,
|
||||
linkPreviews: Optional<List<LinkPreview>>,
|
||||
mentions: Optional<List<Mention>>,
|
||||
sticker: Optional<Attachment>,
|
||||
serverGuid: String?,
|
||||
giftBadge: GiftBadge?,
|
||||
activatePaymentsRequest: Boolean,
|
||||
paymentsActivated: Boolean,
|
||||
messageRanges: BodyRangeList? = null
|
||||
) : this(
|
||||
from = from,
|
||||
groupId = if (group.isPresent) GroupId.v2(group.get().masterKey) else null,
|
||||
body = body.orElse(null),
|
||||
isPushMessage = true,
|
||||
storyType = storyType,
|
||||
parentStoryId = parentStoryId,
|
||||
isStoryReaction = isStoryReaction,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
serverTimeMillis = serverTimeMillis,
|
||||
receivedTimeMillis = receivedTimeMillis,
|
||||
subscriptionId = subscriptionId,
|
||||
expiresIn = expiresIn,
|
||||
isExpirationUpdate = expirationUpdate,
|
||||
quote = quote.orElse(null),
|
||||
isUnidentified = unidentified,
|
||||
isViewOnce = viewOnce,
|
||||
serverGuid = serverGuid,
|
||||
attachments = PointerAttachment.forPointers(attachments).apply { if (sticker.isPresent) add(sticker.get()) },
|
||||
sharedContacts = sharedContacts.orElse(emptyList()),
|
||||
linkPreviews = linkPreviews.orElse(emptyList()),
|
||||
mentions = mentions.orElse(emptyList()),
|
||||
giftBadge = giftBadge,
|
||||
isActivatePaymentsRequest = activatePaymentsRequest,
|
||||
isPaymentsActivated = paymentsActivated,
|
||||
messageRanges = messageRanges
|
||||
)
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package org.thoughtcrime.securesms.mms
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.Attachment
|
||||
import org.thoughtcrime.securesms.contactshare.Contact
|
||||
import org.thoughtcrime.securesms.database.MessageType
|
||||
import org.thoughtcrime.securesms.database.model.Mention
|
||||
import org.thoughtcrime.securesms.database.model.ParentStoryId
|
||||
import org.thoughtcrime.securesms.database.model.StoryType
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
class IncomingMessage(
|
||||
val from: RecipientId,
|
||||
val groupId: GroupId? = null,
|
||||
val groupContext: MessageGroupContext? = null,
|
||||
val body: String? = null,
|
||||
val isPushMessage: Boolean = false,
|
||||
val storyType: StoryType = StoryType.NONE,
|
||||
val parentStoryId: ParentStoryId? = null,
|
||||
val isStoryReaction: Boolean = false,
|
||||
val sentTimeMillis: Long,
|
||||
val serverTimeMillis: Long,
|
||||
val receivedTimeMillis: Long,
|
||||
val subscriptionId: Int = -1,
|
||||
val expiresIn: Long = 0,
|
||||
val isExpirationUpdate: Boolean = false,
|
||||
val quote: QuoteModel? = null,
|
||||
val isUnidentified: Boolean = false,
|
||||
val isViewOnce: Boolean = false,
|
||||
val serverGuid: String? = null,
|
||||
val messageRanges: BodyRangeList? = null,
|
||||
attachments: List<Attachment> = emptyList(),
|
||||
sharedContacts: List<Contact> = emptyList(),
|
||||
linkPreviews: List<LinkPreview> = emptyList(),
|
||||
mentions: List<Mention> = emptyList(),
|
||||
val giftBadge: GiftBadge? = null,
|
||||
val type: MessageType = MessageType.NORMAL
|
||||
) {
|
||||
|
||||
val attachments: List<Attachment> = ArrayList(attachments)
|
||||
val sharedContacts: List<Contact> = ArrayList(sharedContacts)
|
||||
val linkPreviews: List<LinkPreview> = ArrayList(linkPreviews)
|
||||
val mentions: List<Mention> = ArrayList(mentions)
|
||||
|
||||
val isGroupMessage: Boolean = groupId != null
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun identityUpdate(from: RecipientId, sentTimestamp: Long, groupId: GroupId?): IncomingMessage {
|
||||
return IncomingMessage(
|
||||
from = from,
|
||||
sentTimeMillis = sentTimestamp,
|
||||
serverTimeMillis = -1,
|
||||
receivedTimeMillis = sentTimestamp,
|
||||
groupId = groupId,
|
||||
type = MessageType.IDENTITY_UPDATE
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun identityVerified(from: RecipientId, sentTimestamp: Long, groupId: GroupId?): IncomingMessage {
|
||||
return IncomingMessage(
|
||||
from = from,
|
||||
sentTimeMillis = sentTimestamp,
|
||||
serverTimeMillis = -1,
|
||||
receivedTimeMillis = sentTimestamp,
|
||||
groupId = groupId,
|
||||
type = MessageType.IDENTITY_VERIFIED
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun identityDefault(from: RecipientId, sentTimestamp: Long, groupId: GroupId?): IncomingMessage {
|
||||
return IncomingMessage(
|
||||
from = from,
|
||||
sentTimeMillis = sentTimestamp,
|
||||
serverTimeMillis = -1,
|
||||
receivedTimeMillis = sentTimestamp,
|
||||
groupId = groupId,
|
||||
type = MessageType.IDENTITY_DEFAULT
|
||||
)
|
||||
}
|
||||
|
||||
fun contactJoined(from: RecipientId, currentTime: Long): IncomingMessage {
|
||||
return IncomingMessage(
|
||||
from = from,
|
||||
sentTimeMillis = currentTime,
|
||||
serverTimeMillis = -1,
|
||||
receivedTimeMillis = currentTime,
|
||||
type = MessageType.CONTACT_JOINED
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun groupUpdate(from: RecipientId, timestamp: Long, groupId: GroupId, groupContext: DecryptedGroupV2Context): IncomingMessage {
|
||||
val messageGroupContext = MessageGroupContext(groupContext)
|
||||
|
||||
return IncomingMessage(
|
||||
from = from,
|
||||
sentTimeMillis = timestamp,
|
||||
receivedTimeMillis = timestamp,
|
||||
serverTimeMillis = timestamp,
|
||||
groupId = groupId,
|
||||
groupContext = messageGroupContext,
|
||||
body = messageGroupContext.encodedGroupContext,
|
||||
type = MessageType.GROUP_UPDATE
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ import org.thoughtcrime.securesms.database.MessageTable
|
|||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.StoryType
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment
|
||||
|
@ -60,7 +60,7 @@ object ReleaseChannel {
|
|||
Optional.empty()
|
||||
}
|
||||
|
||||
val message = IncomingMediaMessage(
|
||||
val message = IncomingMessage(
|
||||
from = recipientId,
|
||||
sentTimeMillis = System.currentTimeMillis(),
|
||||
serverTimeMillis = System.currentTimeMillis(),
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
public class IncomingEncryptedMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingEncryptedMessage(IncomingTextMessage base, String newBody) {
|
||||
super(base, newBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecureMessage() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
public class IncomingEndSessionMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingEndSessionMessage(IncomingTextMessage base) {
|
||||
this(base, base.getMessageBody());
|
||||
}
|
||||
|
||||
public IncomingEndSessionMessage(IncomingTextMessage base, String newBody) {
|
||||
super(base, newBody);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEndSession() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context;
|
||||
import org.thoughtcrime.securesms.mms.MessageGroupContext;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class IncomingGroupUpdateMessage extends IncomingTextMessage {
|
||||
|
||||
private final MessageGroupContext groupContext;
|
||||
|
||||
public IncomingGroupUpdateMessage(IncomingTextMessage base, DecryptedGroupV2Context groupV2Context) {
|
||||
this(base, new MessageGroupContext(groupV2Context));
|
||||
}
|
||||
|
||||
public IncomingGroupUpdateMessage(IncomingTextMessage base, MessageGroupContext groupContext) {
|
||||
super(base, groupContext.getEncodedGroupContext());
|
||||
this.groupContext = groupContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGroup() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isUpdate() {
|
||||
return GroupV2UpdateMessageUtil.isUpdate(groupContext) || groupContext.requireGroupV1Properties().isUpdate();
|
||||
}
|
||||
|
||||
public boolean isGroupV2() {
|
||||
return GroupV2UpdateMessageUtil.isGroupV2(groupContext);
|
||||
}
|
||||
|
||||
public boolean isQuit() {
|
||||
return !isGroupV2() && groupContext.requireGroupV1Properties().isQuit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJustAGroupLeave() {
|
||||
return GroupV2UpdateMessageUtil.isJustAGroupLeave(groupContext);
|
||||
}
|
||||
|
||||
public boolean isCancelJoinRequest() {
|
||||
return GroupV2UpdateMessageUtil.isJoinRequestCancel(groupContext);
|
||||
}
|
||||
|
||||
public int getChangeRevision() {
|
||||
return GroupV2UpdateMessageUtil.getChangeRevision(groupContext);
|
||||
}
|
||||
|
||||
public Optional<ServiceId> getChangeEditor() {
|
||||
return GroupV2UpdateMessageUtil.getChangeEditor(groupContext);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
|
||||
public class IncomingIdentityDefaultMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingIdentityDefaultMessage(IncomingTextMessage base) {
|
||||
super(base, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentityDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
public class IncomingIdentityUpdateMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingIdentityUpdateMessage(IncomingTextMessage base) {
|
||||
super(base, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentityUpdate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
|
||||
public class IncomingIdentityVerifiedMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingIdentityVerifiedMessage(IncomingTextMessage base) {
|
||||
super(base, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentityVerified() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
public class IncomingJoinedMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingJoinedMessage(RecipientId sender) {
|
||||
super(sender, 1, System.currentTimeMillis(), -1, System.currentTimeMillis(), null, Optional.empty(), 0, false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJoined() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecureMessage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,294 +0,0 @@
|
|||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.telephony.SmsMessage;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class IncomingTextMessage implements Parcelable {
|
||||
|
||||
public static final Parcelable.Creator<IncomingTextMessage> CREATOR = new Parcelable.Creator<IncomingTextMessage>() {
|
||||
@Override
|
||||
public IncomingTextMessage createFromParcel(Parcel in) {
|
||||
return new IncomingTextMessage(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IncomingTextMessage[] newArray(int size) {
|
||||
return new IncomingTextMessage[size];
|
||||
}
|
||||
};
|
||||
private static final String TAG = Log.tag(IncomingTextMessage.class);
|
||||
|
||||
private final String message;
|
||||
private final RecipientId authorId;
|
||||
private final int senderDeviceId;
|
||||
private final int protocol;
|
||||
private final String serviceCenterAddress;
|
||||
private final boolean replyPathPresent;
|
||||
private final String pseudoSubject;
|
||||
private final long sentTimestampMillis;
|
||||
private final long serverTimestampMillis;
|
||||
private final long receivedTimestampMillis;
|
||||
@Nullable private final GroupId groupId;
|
||||
private final boolean push;
|
||||
private final int subscriptionId;
|
||||
private final long expiresInMillis;
|
||||
private final boolean unidentified;
|
||||
@Nullable private final String serverGuid;
|
||||
|
||||
public IncomingTextMessage(@NonNull RecipientId authorId, @NonNull SmsMessage message, int subscriptionId) {
|
||||
this.message = message.getDisplayMessageBody();
|
||||
this.authorId = authorId;
|
||||
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
this.protocol = message.getProtocolIdentifier();
|
||||
this.serviceCenterAddress = message.getServiceCenterAddress();
|
||||
this.replyPathPresent = message.isReplyPathPresent();
|
||||
this.pseudoSubject = message.getPseudoSubject();
|
||||
this.sentTimestampMillis = message.getTimestampMillis();
|
||||
this.serverTimestampMillis = -1;
|
||||
this.receivedTimestampMillis = System.currentTimeMillis();
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresInMillis = 0;
|
||||
this.groupId = null;
|
||||
this.push = false;
|
||||
this.unidentified = false;
|
||||
this.serverGuid = null;
|
||||
}
|
||||
|
||||
public IncomingTextMessage(@NonNull RecipientId authorId,
|
||||
int senderDeviceId,
|
||||
long sentTimestampMillis,
|
||||
long serverTimestampMillis,
|
||||
long receivedTimestampMillis,
|
||||
String encodedBody,
|
||||
Optional<GroupId> groupId,
|
||||
long expiresInMillis,
|
||||
boolean unidentified,
|
||||
String serverGuid)
|
||||
{
|
||||
this.message = encodedBody;
|
||||
this.authorId = authorId;
|
||||
this.senderDeviceId = senderDeviceId;
|
||||
this.protocol = 31337;
|
||||
this.serviceCenterAddress = "GCM";
|
||||
this.replyPathPresent = true;
|
||||
this.pseudoSubject = "";
|
||||
this.sentTimestampMillis = sentTimestampMillis;
|
||||
this.serverTimestampMillis = serverTimestampMillis;
|
||||
this.receivedTimestampMillis = receivedTimestampMillis;
|
||||
this.push = true;
|
||||
this.subscriptionId = -1;
|
||||
this.expiresInMillis = expiresInMillis;
|
||||
this.unidentified = unidentified;
|
||||
this.groupId = groupId.orElse(null);
|
||||
this.serverGuid = serverGuid;
|
||||
}
|
||||
|
||||
public IncomingTextMessage(Parcel in) {
|
||||
this.message = in.readString();
|
||||
this.authorId = in.readParcelable(IncomingTextMessage.class.getClassLoader());
|
||||
this.senderDeviceId = in.readInt();
|
||||
this.protocol = in.readInt();
|
||||
this.serviceCenterAddress = in.readString();
|
||||
this.replyPathPresent = (in.readInt() == 1);
|
||||
this.pseudoSubject = in.readString();
|
||||
this.sentTimestampMillis = in.readLong();
|
||||
this.serverTimestampMillis = in.readLong();
|
||||
this.receivedTimestampMillis = in.readLong();
|
||||
this.groupId = GroupId.parseNullableOrThrow(in.readString());
|
||||
this.push = (in.readInt() == 1);
|
||||
this.subscriptionId = in.readInt();
|
||||
this.expiresInMillis = in.readLong();
|
||||
this.unidentified = in.readInt() == 1;
|
||||
this.serverGuid = in.readString();
|
||||
}
|
||||
|
||||
public IncomingTextMessage(IncomingTextMessage base, String newBody) {
|
||||
this.message = newBody;
|
||||
this.authorId = base.getAuthorId();
|
||||
this.senderDeviceId = base.getAuthorDeviceId();
|
||||
this.protocol = base.getProtocol();
|
||||
this.serviceCenterAddress = base.getServiceCenterAddress();
|
||||
this.replyPathPresent = base.isReplyPathPresent();
|
||||
this.pseudoSubject = base.getPseudoSubject();
|
||||
this.sentTimestampMillis = base.getSentTimestampMillis();
|
||||
this.serverTimestampMillis = base.getServerTimestampMillis();
|
||||
this.receivedTimestampMillis = base.getReceivedTimestampMillis();
|
||||
this.groupId = base.getGroupId();
|
||||
this.push = base.isPush();
|
||||
this.subscriptionId = base.getSubscriptionId();
|
||||
this.expiresInMillis = base.getExpiresIn();
|
||||
this.unidentified = base.isUnidentified();
|
||||
this.serverGuid = base.getServerGuid();
|
||||
}
|
||||
|
||||
public IncomingTextMessage(List<IncomingTextMessage> fragments) {
|
||||
StringBuilder body = new StringBuilder();
|
||||
|
||||
for (IncomingTextMessage message : fragments) {
|
||||
body.append(message.getMessageBody());
|
||||
}
|
||||
|
||||
this.message = body.toString();
|
||||
this.authorId = fragments.get(0).getAuthorId();
|
||||
this.senderDeviceId = fragments.get(0).getAuthorDeviceId();
|
||||
this.protocol = fragments.get(0).getProtocol();
|
||||
this.serviceCenterAddress = fragments.get(0).getServiceCenterAddress();
|
||||
this.replyPathPresent = fragments.get(0).isReplyPathPresent();
|
||||
this.pseudoSubject = fragments.get(0).getPseudoSubject();
|
||||
this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis();
|
||||
this.serverTimestampMillis = fragments.get(0).getServerTimestampMillis();
|
||||
this.receivedTimestampMillis = fragments.get(0).getReceivedTimestampMillis();
|
||||
this.groupId = fragments.get(0).getGroupId();
|
||||
this.push = fragments.get(0).isPush();
|
||||
this.subscriptionId = fragments.get(0).getSubscriptionId();
|
||||
this.expiresInMillis = fragments.get(0).getExpiresIn();
|
||||
this.unidentified = fragments.get(0).isUnidentified();
|
||||
this.serverGuid = fragments.get(0).getServerGuid();
|
||||
}
|
||||
|
||||
public int getSubscriptionId() {
|
||||
return subscriptionId;
|
||||
}
|
||||
|
||||
public long getExpiresIn() {
|
||||
return expiresInMillis;
|
||||
}
|
||||
|
||||
public long getSentTimestampMillis() {
|
||||
return sentTimestampMillis;
|
||||
}
|
||||
|
||||
public long getServerTimestampMillis() {
|
||||
return serverTimestampMillis;
|
||||
}
|
||||
|
||||
public long getReceivedTimestampMillis() {
|
||||
return receivedTimestampMillis;
|
||||
}
|
||||
|
||||
public String getPseudoSubject() {
|
||||
return pseudoSubject;
|
||||
}
|
||||
|
||||
public String getMessageBody() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public RecipientId getAuthorId() {
|
||||
return authorId;
|
||||
}
|
||||
|
||||
public int getAuthorDeviceId() {
|
||||
return senderDeviceId;
|
||||
}
|
||||
|
||||
public int getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public String getServiceCenterAddress() {
|
||||
return serviceCenterAddress;
|
||||
}
|
||||
|
||||
public boolean isReplyPathPresent() {
|
||||
return replyPathPresent;
|
||||
}
|
||||
|
||||
public boolean isSecureMessage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPreKeyBundle() {
|
||||
return isLegacyPreKeyBundle() || isContentPreKeyBundle();
|
||||
}
|
||||
|
||||
public boolean isLegacyPreKeyBundle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isContentPreKeyBundle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isEndSession() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPush() {
|
||||
return push;
|
||||
}
|
||||
|
||||
public @Nullable GroupId getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public boolean isGroup() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isJoined() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIdentityUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIdentityVerified() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIdentityDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True iff the message is only a group leave of a single member.
|
||||
*/
|
||||
public boolean isJustAGroupLeave() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isUnidentified() {
|
||||
return unidentified;
|
||||
}
|
||||
|
||||
public @Nullable String getServerGuid() {
|
||||
return serverGuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(message);
|
||||
out.writeParcelable(authorId, flags);
|
||||
out.writeInt(senderDeviceId);
|
||||
out.writeInt(protocol);
|
||||
out.writeString(serviceCenterAddress);
|
||||
out.writeInt(replyPathPresent ? 1 : 0);
|
||||
out.writeString(pseudoSubject);
|
||||
out.writeLong(sentTimestampMillis);
|
||||
out.writeString(groupId == null ? null : groupId.toString());
|
||||
out.writeInt(push ? 1 : 0);
|
||||
out.writeInt(subscriptionId);
|
||||
out.writeLong(expiresInMillis);
|
||||
out.writeInt(unidentified ? 1 : 0);
|
||||
out.writeString(serverGuid);
|
||||
}
|
||||
}
|
|
@ -25,15 +25,12 @@ import org.thoughtcrime.securesms.database.SignalDatabase;
|
|||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMessage;
|
||||
import org.thoughtcrime.securesms.notifications.v2.ConversationId;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.sms.IncomingIdentityDefaultMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingIdentityUpdateMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingIdentityVerifiedMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
|
||||
import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
|
||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||
|
@ -76,12 +73,14 @@ public final class IdentityUtil {
|
|||
if (groupRecord.getMembers().contains(recipient.getId()) && groupRecord.isActive() && !groupRecord.isMms()) {
|
||||
|
||||
if (remote) {
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, time, null, Optional.of(groupRecord.getId()), 0, false, null);
|
||||
IncomingMessage incoming = verified ? IncomingMessage.identityVerified(recipient.getId(), time, groupRecord.getId())
|
||||
: IncomingMessage.identityDefault(recipient.getId(), time, groupRecord.getId());
|
||||
|
||||
if (verified) incoming = new IncomingIdentityVerifiedMessage(incoming);
|
||||
else incoming = new IncomingIdentityDefaultMessage(incoming);
|
||||
|
||||
smsDatabase.insertMessageInbox(incoming);
|
||||
try {
|
||||
smsDatabase.insertMessageInbox(incoming);
|
||||
} catch (MmsException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
} else {
|
||||
RecipientId recipientId = SignalDatabase.recipients().getOrInsertFromGroupId(groupRecord.getId());
|
||||
Recipient groupRecipient = Recipient.resolved(recipientId);
|
||||
|
@ -106,12 +105,14 @@ public final class IdentityUtil {
|
|||
}
|
||||
|
||||
if (remote) {
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, time, null, Optional.empty(), 0, false, null);
|
||||
IncomingMessage incoming = verified ? IncomingMessage.identityVerified(recipient.getId(), time, null)
|
||||
: IncomingMessage.identityDefault(recipient.getId(), time, null);
|
||||
|
||||
if (verified) incoming = new IncomingIdentityVerifiedMessage(incoming);
|
||||
else incoming = new IncomingIdentityDefaultMessage(incoming);
|
||||
|
||||
smsDatabase.insertMessageInbox(incoming);
|
||||
try {
|
||||
smsDatabase.insertMessageInbox(incoming);
|
||||
} catch (MmsException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
} else {
|
||||
OutgoingMessage outgoing;
|
||||
if (verified) {
|
||||
|
@ -144,21 +145,25 @@ public final class IdentityUtil {
|
|||
|
||||
while ((groupRecord = reader.getNext()) != null) {
|
||||
if (groupRecord.getMembers().contains(recipientId) && groupRecord.isActive()) {
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipientId, 1, time, time, time, null, Optional.of(groupRecord.getId()), 0, false, null);
|
||||
IncomingIdentityUpdateMessage groupUpdate = new IncomingIdentityUpdateMessage(incoming);
|
||||
|
||||
IncomingMessage groupUpdate = IncomingMessage.identityUpdate(recipientId, time, groupRecord.getId());
|
||||
smsDatabase.insertMessageInbox(groupUpdate);
|
||||
}
|
||||
}
|
||||
} catch (MmsException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipientId, 1, time, -1, time, null, Optional.empty(), 0, false, null);
|
||||
IncomingIdentityUpdateMessage individualUpdate = new IncomingIdentityUpdateMessage(incoming);
|
||||
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(individualUpdate);
|
||||
try {
|
||||
IncomingMessage individualUpdate = IncomingMessage.identityUpdate(recipientId, time, null);
|
||||
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(individualUpdate);
|
||||
|
||||
if (insertResult.isPresent()) {
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context, ConversationId.forConversation(insertResult.get().getThreadId()));
|
||||
if (insertResult.isPresent()) {
|
||||
ApplicationDependencies.getMessageNotifier().updateNotification(context, ConversationId.forConversation(insertResult.get().getThreadId()));
|
||||
}
|
||||
} catch (MmsException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void saveIdentity(String user, IdentityKey identityKey) {
|
||||
|
|
|
@ -35,8 +35,6 @@ import org.thoughtcrime.securesms.database.MessageTypes.INVALID_MESSAGE_TYPE
|
|||
import org.thoughtcrime.securesms.database.MessageTypes.JOINED_TYPE
|
||||
import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_BIT
|
||||
import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_BUNDLE_BIT
|
||||
import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_CONTENT_FORMAT
|
||||
import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_CORRUPTED_BIT
|
||||
import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT
|
||||
import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_IDENTITY_UPDATE_BIT
|
||||
import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT
|
||||
|
@ -100,10 +98,8 @@ object MessageBitmaskColumnTransformer : ColumnTransformer {
|
|||
isKeyExchangeType:${type and KEY_EXCHANGE_BIT != 0L}
|
||||
isIdentityVerified:${type and KEY_EXCHANGE_IDENTITY_VERIFIED_BIT != 0L}
|
||||
isIdentityDefault:${type and KEY_EXCHANGE_IDENTITY_DEFAULT_BIT != 0L}
|
||||
isCorruptedKeyExchange:${type and KEY_EXCHANGE_CORRUPTED_BIT != 0L}
|
||||
isInvalidVersionKeyExchange:${type and KEY_EXCHANGE_INVALID_VERSION_BIT != 0L}
|
||||
isBundleKeyExchange:${type and KEY_EXCHANGE_BUNDLE_BIT != 0L}
|
||||
isContentBundleKeyExchange:${type and KEY_EXCHANGE_CONTENT_FORMAT != 0L}
|
||||
isIdentityUpdate:${type and KEY_EXCHANGE_IDENTITY_UPDATE_BIT != 0L}
|
||||
isRateLimited:${type and MESSAGE_RATE_LIMITED_BIT != 0L}
|
||||
isExpirationTimerUpdate:${type and EXPIRATION_TIMER_UPDATE_BIT != 0L}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package org.thoughtcrime.securesms.database
|
||||
|
||||
import android.content.ContentValues
|
||||
import org.signal.core.util.orNull
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.mms.IncomingMessage
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import android.database.sqlite.SQLiteDatabase as AndroidSQLiteDatabase
|
||||
|
@ -29,17 +30,16 @@ object TestSms {
|
|||
unread: Boolean = false,
|
||||
threadId: Long = 1
|
||||
): Long {
|
||||
val message = IncomingTextMessage(
|
||||
sender,
|
||||
senderDeviceId,
|
||||
sentTimestampMillis,
|
||||
serverTimestampMillis,
|
||||
receivedTimestampMillis,
|
||||
encodedBody,
|
||||
groupId,
|
||||
expiresInMillis,
|
||||
unidentified,
|
||||
serverGuid
|
||||
val message = IncomingMessage(
|
||||
from = sender,
|
||||
sentTimeMillis = sentTimestampMillis,
|
||||
serverTimeMillis = serverTimestampMillis,
|
||||
receivedTimeMillis = receivedTimestampMillis,
|
||||
body = encodedBody,
|
||||
groupId = groupId.orNull(),
|
||||
expiresIn = expiresInMillis,
|
||||
isUnidentified = unidentified,
|
||||
serverGuid = serverGuid
|
||||
)
|
||||
|
||||
return insert(
|
||||
|
@ -53,23 +53,22 @@ object TestSms {
|
|||
|
||||
fun insert(
|
||||
db: AndroidSQLiteDatabase,
|
||||
message: IncomingTextMessage,
|
||||
message: IncomingMessage,
|
||||
type: Long = MessageTypes.BASE_INBOX_TYPE,
|
||||
unread: Boolean = false,
|
||||
threadId: Long = 1
|
||||
): Long {
|
||||
val values = ContentValues().apply {
|
||||
put(MessageTable.FROM_RECIPIENT_ID, message.authorId.serialize())
|
||||
put(MessageTable.FROM_DEVICE_ID, message.authorDeviceId)
|
||||
put(MessageTable.TO_RECIPIENT_ID, message.authorId.serialize())
|
||||
put(MessageTable.DATE_RECEIVED, message.receivedTimestampMillis)
|
||||
put(MessageTable.DATE_SENT, message.sentTimestampMillis)
|
||||
put(MessageTable.DATE_SERVER, message.serverTimestampMillis)
|
||||
put(MessageTable.FROM_RECIPIENT_ID, message.from.serialize())
|
||||
put(MessageTable.TO_RECIPIENT_ID, message.from.serialize())
|
||||
put(MessageTable.DATE_RECEIVED, message.receivedTimeMillis)
|
||||
put(MessageTable.DATE_SENT, message.sentTimeMillis)
|
||||
put(MessageTable.DATE_SERVER, message.serverTimeMillis)
|
||||
put(MessageTable.READ, if (unread) 0 else 1)
|
||||
put(MessageTable.SMS_SUBSCRIPTION_ID, message.subscriptionId)
|
||||
put(MessageTable.EXPIRES_IN, message.expiresIn)
|
||||
put(MessageTable.UNIDENTIFIED, message.isUnidentified)
|
||||
put(MessageTable.BODY, message.messageBody)
|
||||
put(MessageTable.BODY, message.body)
|
||||
put(MessageTable.TYPE, type)
|
||||
put(MessageTable.THREAD_ID, threadId)
|
||||
put(MessageTable.SERVER_GUID, message.serverGuid)
|
||||
|
|
Loading…
Add table
Reference in a new issue