From 34fab9681ceaa7d23a038bbf8b7c5c736fec8e26 Mon Sep 17 00:00:00 2001 From: jubb Date: Thu, 11 Feb 2021 14:01:31 +1100 Subject: [PATCH] fix: closed groups info messages work now --- .../securesms/database/GroupDatabase.java | 5 +- .../securesms/database/MmsSmsDatabase.java | 10 +- .../securesms/database/Storage.kt | 3 +- .../securesms/groups/GroupManager.java | 2 +- .../groups/GroupMessageProcessor.java | 12 +- .../securesms/jobs/PushDecryptJob.java | 113 +------------- .../loki/database/LokiMessageDatabase.kt | 2 +- .../ClosedGroupUpdateMessageSendJobV2.kt | 13 +- .../loki/protocol/ClosedGroupsProtocol.kt | 4 +- .../loki/protocol/ClosedGroupsProtocolV2.kt | 140 ++++++++++++------ .../mms/OutgoingGroupMediaMessage.java | 1 - .../api/SignalServiceMessageSender.java | 1 - 12 files changed, 130 insertions(+), 176 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java index f17e6aca8c..164172aba1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java @@ -184,7 +184,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt } } - public void create(@NonNull String groupId, @Nullable String title, @NonNull List
members, + public long create(@NonNull String groupId, @Nullable String title, @NonNull List
members, @Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay, @Nullable List
admins) { Collections.sort(members); @@ -211,7 +211,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt contentValues.put(ADMINS, Address.Companion.toSerializedList(admins, ',')); } - databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues); + long threadId = databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues); Recipient.applyCached(Address.Companion.fromSerialized(groupId), recipient -> { recipient.setName(title); @@ -220,6 +220,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt }); notifyConversationListListeners(); + return threadId; } public boolean delete(@NonNull String groupId) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java index 0ddf142866..159d961816 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java @@ -87,7 +87,7 @@ public class MmsSmsDatabase extends Database { } } - public @Nullable MessageRecord getMessageFor(long timestamp, Address author) { + public @Nullable MessageRecord getMessageFor(long timestamp, String serializedAuthor) { MmsSmsDatabase db = DatabaseFactory.getMmsSmsDatabase(context); try (Cursor cursor = queryTables(PROJECTION, MmsSmsColumns.NORMALIZED_DATE_SENT + " = " + timestamp, null, null)) { @@ -96,8 +96,8 @@ public class MmsSmsDatabase extends Database { MessageRecord messageRecord; while ((messageRecord = reader.getNext()) != null) { - if ((Util.isOwnNumber(context, author.serialize()) && messageRecord.isOutgoing()) || - (!Util.isOwnNumber(context, author.serialize()) && messageRecord.getIndividualRecipient().getAddress().equals(author))) + if ((Util.isOwnNumber(context, serializedAuthor) && messageRecord.isOutgoing()) || + (!Util.isOwnNumber(context, serializedAuthor) && messageRecord.getIndividualRecipient().getAddress().equals(serializedAuthor))) { return messageRecord; } @@ -107,6 +107,10 @@ public class MmsSmsDatabase extends Database { return null; } + public @Nullable MessageRecord getMessageFor(long timestamp, Address author) { + return getMessageFor(timestamp, author.serialize()); + } + public Cursor getConversation(long threadId, long offset, long limit) { String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC"; String selection = MmsSmsColumns.THREAD_ID + " = " + threadId; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 3f34547fde..984f9fb82c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -8,7 +8,6 @@ import org.session.libsession.messaging.jobs.AttachmentUploadJob import org.session.libsession.messaging.jobs.Job import org.session.libsession.messaging.jobs.JobQueue import org.session.libsession.messaging.jobs.MessageSendJob -import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.messages.visible.Attachment import org.session.libsession.messaging.messages.visible.VisibleMessage import org.session.libsession.messaging.opengroups.OpenGroup @@ -351,7 +350,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, .setName(name) .addAllMembers(members) .addAllAdmins(admins) - val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, System.currentTimeMillis(), 0, null, listOf(), listOf()) + val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, 0, null, listOf(), listOf()) val mmsDB = DatabaseFactory.getMmsDatabase(context) val infoMessageID = mmsDB.insertMessageOutbox(infoMessage, threadID, false, null) mmsDB.markAsSent(infoMessageID, true) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java index 6d9ac5e29a..af11e476c4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java @@ -194,7 +194,7 @@ public class GroupManager { avatarAttachment = new UriAttachment(avatarUri, MediaTypes.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null, false, false, null, null); } - OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0, null, Collections.emptyList(), Collections.emptyList()); + OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, 0, null, Collections.emptyList(), Collections.emptyList()); long threadId = MessageSender.send(context, outgoingMessage, -1, false, null); return new GroupActionResult(groupRecipient, threadId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java index e6d9090021..e6474ce4b7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupMessageProcessor.java @@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult; import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.SmsDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase; +import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.jobs.AvatarDownloadJob; import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob; import org.session.libsignal.utilities.logging.Log; @@ -269,9 +270,16 @@ public class GroupMessageProcessor { MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context); Address address = Address.Companion.fromExternal(context, GroupUtil.getEncodedId(group)); Recipient recipient = Recipient.from(context, address, false); - OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipient, storage, null, content.getTimestamp(), 0, null, Collections.emptyList(), Collections.emptyList()); + OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipient, storage, null, 0, null, Collections.emptyList(), Collections.emptyList()); long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); - long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null); + Address senderAddress = Address.Companion.fromExternal(context, content.getSender()); + MessageRecord existingMessage = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(content.getTimestamp(), senderAddress); + long messageId; + if (existingMessage != null) { + messageId = existingMessage.getId(); + } else { + messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null); + } mmsDatabase.markAsSent(messageId, true); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 40cfb1fdc2..85b27d315e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -47,7 +47,6 @@ import org.session.libsession.utilities.TextSecurePreferences; import org.thoughtcrime.securesms.contactshare.ContactModelMapper; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; -import org.thoughtcrime.securesms.crypto.SecurityEvent; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl; import org.thoughtcrime.securesms.database.AttachmentDatabase; @@ -83,7 +82,6 @@ import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2; import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol; import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol; import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation; -import org.thoughtcrime.securesms.loki.utilities.DatabaseUtilitiesKt; import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities; import org.thoughtcrime.securesms.mms.IncomingMediaMessage; import org.thoughtcrime.securesms.mms.MmsException; @@ -97,7 +95,6 @@ import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage; import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage; import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage; -import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.session.libsignal.utilities.Hex; import org.session.libsignal.libsignal.InvalidMessageException; @@ -399,33 +396,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType { } } - private long handleSynchronizeSentEndSessionMessage(@NonNull SentTranscriptMessage message) - { - SmsDatabase database = DatabaseFactory.getSmsDatabase(context); - Recipient recipient = getSyncMessageDestination(message); - OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipient, "", -1); - OutgoingEndSessionMessage outgoingEndSessionMessage = new OutgoingEndSessionMessage(outgoingTextMessage); - - long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); - - if (!recipient.isGroupRecipient()) { - // TODO: Handle session reset on sync messages - /* - SessionStore sessionStore = new TextSecureSessionStore(context); - sessionStore.deleteAllSessions(recipient.getAddress().toPhoneString()); - */ - - SecurityEvent.broadcastSecurityUpdateEvent(context); - - long messageId = database.insertMessageOutbox(threadId, outgoingEndSessionMessage, - false, message.getTimestamp(), - null); - database.markAsSent(messageId, true); - } - - return threadId; - } - private void handleGroupMessage(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message, @NonNull Optional smsMessageId) @@ -484,83 +454,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType { } } - private void handleSynchronizeStickerPackOperation(@NonNull List stickerPackOperations) { - JobManager jobManager = ApplicationContext.getInstance(context).getJobManager(); - - for (StickerPackOperationMessage operation : stickerPackOperations) { - if (operation.getPackId().isPresent() && operation.getPackKey().isPresent() && operation.getType().isPresent()) { - String packId = Hex.toStringCondensed(operation.getPackId().get()); - String packKey = Hex.toStringCondensed(operation.getPackKey().get()); - - switch (operation.getType().get()) { - case INSTALL: - jobManager.add(new StickerPackDownloadJob(packId, packKey, false)); - break; - case REMOVE: - DatabaseFactory.getStickerDatabase(context).uninstallPack(packId); - break; - } - } else { - Log.w(TAG, "Received incomplete sticker pack operation sync."); - } - } - } - - private void handleSynchronizeSentMessage(@NonNull SignalServiceContent content, - @NonNull SentTranscriptMessage message) - throws StorageFailedException - - { - try { - GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); - - Long threadId; - - if (message.getMessage().isEndSession()) { - threadId = handleSynchronizeSentEndSessionMessage(message); - } else if (message.getMessage().isGroupUpdate()) { - threadId = GroupMessageProcessor.process(context, content, message.getMessage(), true); - } else if (message.getMessage().isExpirationUpdate()) { - threadId = handleSynchronizeSentExpirationUpdate(message); - } else if (message.getMessage().getAttachments().isPresent() || message.getMessage().getQuote().isPresent() || message.getMessage().getPreviews().isPresent() || message.getMessage().getSticker().isPresent()) { - threadId = handleSynchronizeSentMediaMessage(message); - } else { - threadId = handleSynchronizeSentTextMessage(message); - } - - if (threadId == -1L) { threadId = null; } - - if (message.getMessage().getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get()))) { - handleUnknownGroupMessage(content, message.getMessage().getGroupInfo().get()); - } - - if (message.getMessage().getProfileKey().isPresent()) { - Recipient recipient = null; - - if (message.getDestination().isPresent()) recipient = Recipient.from(context, Address.Companion.fromSerialized(message.getDestination().get()), false); - else if (message.getMessage().getGroupInfo().isPresent()) recipient = Recipient.from(context, Address.Companion.fromSerialized(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get())), false); - - - if (recipient != null && !recipient.isSystemContact() && !recipient.isProfileSharing()) { - DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true); - } - - SessionMetaProtocol.handleProfileKeyUpdate(context, content); - } - - SessionMetaProtocol.handleProfileUpdateIfNeeded(context, content); - - if (threadId != null) { - DatabaseFactory.getThreadDatabase(context).setRead(threadId, true); - messageNotifier.updateNotification(context); - } - - messageNotifier.setLastDesktopActivityTimestamp(message.getTimestamp()); - } catch (MmsException e) { - throw new StorageFailedException(e, content.getSender(), content.getSenderDevice()); - } - } - public void handleMediaMessage(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message, @NonNull Optional smsMessageId, @@ -1429,6 +1322,12 @@ public class PushDecryptJob extends BaseJob implements InjectableType { return true; } + if (content.getSender().equals(TextSecurePreferences.getLocalNumber(context)) && + DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(content.getTimestamp(), content.getSender()) != null) { + Log.d("Loki", "Skipping message from self we already have"); + return true; + } + Recipient sender = Recipient.from(context, Address.Companion.fromSerialized(content.getSender()), false); if (content.getDeviceLink().isPresent()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiMessageDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiMessageDatabase.kt index 108783a51f..66c1907405 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiMessageDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiMessageDatabase.kt @@ -29,7 +29,7 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab } override fun getQuoteServerID(quoteID: Long, quoteePublicKey: String): Long? { - val message = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(quoteID, Address.fromSerialized(quoteePublicKey)) + val message = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(quoteID, quoteePublicKey) return if (message != null) getServerID(message.getId()) else null } diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupUpdateMessageSendJobV2.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupUpdateMessageSendJobV2.kt index 8ae19749e5..6b4060aa17 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupUpdateMessageSendJobV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupUpdateMessageSendJobV2.kt @@ -27,7 +27,7 @@ import org.session.libsignal.utilities.Hex import java.util.* import java.util.concurrent.TimeUnit -class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Parameters, private val destination: String, private val kind: Kind) : BaseJob(parameters) { +class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Parameters, private val destination: String, private val kind: Kind, private val sentTime: Long) : BaseJob(parameters) { sealed class Kind { class New(val publicKey: ByteArray, val name: String, val encryptionKeyPair: ECKeyPair, val members: Collection, val admins: Collection) : Kind() @@ -61,20 +61,22 @@ class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Paramete } } - constructor(destination: String, kind: Kind) : this(Parameters.Builder() + constructor(destination: String, kind: Kind, sentTime: Long) : this(Parameters.Builder() .addConstraint(NetworkConstraint.KEY) .setQueue(KEY) .setLifespan(TimeUnit.DAYS.toMillis(1)) .setMaxAttempts(20) .build(), destination, - kind) + kind, + sentTime) override fun getFactoryKey(): String { return KEY } override fun serialize(): Data { val builder = Data.Builder() builder.putString("destination", destination) + builder.putLong("sentTime", sentTime) when (kind) { is Kind.New -> { builder.putString("kind", "New") @@ -124,6 +126,7 @@ class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Paramete override fun create(parameters: Parameters, data: Data): ClosedGroupUpdateMessageSendJobV2 { val destination = data.getString("destination") val rawKind = data.getString("kind") + val sentTime = data.getLong("sentTime") val kind: Kind when (rawKind) { "New" -> { @@ -162,7 +165,7 @@ class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Paramete } else -> throw Exception("Invalid closed group update message kind: $rawKind.") } - return ClosedGroupUpdateMessageSendJobV2(parameters, destination, kind) + return ClosedGroupUpdateMessageSendJobV2(parameters, destination, kind, sentTime) } } @@ -221,7 +224,7 @@ class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Paramete try { // isClosedGroup can always be false as it's only used in the context of legacy closed groups messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess, - Date().time, serializedContentMessage, false, ttl, false, + sentTime, serializedContentMessage, false, ttl, false, true, false, false, Optional.absent()) } catch (e: Exception) { Log.d("Loki", "Failed to send closed group update message to: $destination due to error: $e.") diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocol.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocol.kt index 3dd347472c..6c47269505 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocol.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocol.kt @@ -285,7 +285,7 @@ object ClosedGroupsProtocol { .setName(name) .addAllMembers(members) .addAllAdmins(admins) - val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, System.currentTimeMillis(), 0, null, listOf(), listOf()) + val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, 0, null, listOf(), listOf()) val mmsDB = DatabaseFactory.getMmsDatabase(context) val infoMessageID = mmsDB.insertMessageOutbox(infoMessage, threadID, false, null) mmsDB.markAsSent(infoMessageID, true) @@ -324,6 +324,6 @@ object ClosedGroupsProtocol { .setId(decodedGroupId) .setType(GroupContext.Type.QUIT) .build() - return OutgoingGroupMediaMessage(groupRecipient, groupContext, null, System.currentTimeMillis(), 0, null, emptyList(), emptyList()) + return OutgoingGroupMediaMessage(groupRecipient, groupContext, null, 0, null, emptyList(), emptyList()) } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt index c97591b879..7395fd2b9c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt @@ -58,6 +58,7 @@ object ClosedGroupsProtocolV2 { val apiDB = DatabaseFactory.getLokiAPIDatabase(context) // Generate the group's public key val groupPublicKey = Curve.generateKeyPair().hexEncodedPublicKey // Includes the "05" prefix + val sentTime = System.currentTimeMillis() // Generate the key pair that'll be used for encryption and decryption val encryptionKeyPair = Curve.generateKeyPair() // Create the group @@ -68,19 +69,20 @@ object ClosedGroupsProtocolV2 { null, null, LinkedList(admins.map { Address.fromSerialized(it!!) })) DatabaseFactory.getRecipientDatabase(context).setProfileSharing(Recipient.from(context, Address.fromSerialized(groupID), false), true) // Send a closed group update message to all members individually - val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJobV2.Kind.New(Hex.fromStringCondensed(groupPublicKey), name, encryptionKeyPair, membersAsData, adminsAsData) - for (member in members) { - val job = ClosedGroupUpdateMessageSendJobV2(member, closedGroupUpdateKind) - job.setContext(context) - job.onRun() // Run the job immediately to make all of this sync - } // Add the group to the user's set of public keys to poll for apiDB.addClosedGroupPublicKey(groupPublicKey) // Store the encryption key pair apiDB.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey) // Notify the user val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID) + insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTime) + + val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJobV2.Kind.New(Hex.fromStringCondensed(groupPublicKey), name, encryptionKeyPair, membersAsData, adminsAsData) + for (member in members) { + val job = ClosedGroupUpdateMessageSendJobV2(member, closedGroupUpdateKind, sentTime) + job.setContext(context) + job.onRun() // Run the job immediately to make all of this sync + } // Notify the PN server LokiPushNotificationManager.performOperation(context, ClosedGroupOperation.Subscribe, groupPublicKey, userPublicKey) // Fulfill the promise @@ -102,13 +104,14 @@ object ClosedGroupsProtocolV2 { val updatedMembers = group.members.map { it.serialize() }.toSet() - userPublicKey val admins = group.admins.map { it.serialize() } val name = group.title + val sentTime = System.currentTimeMillis() if (group == null) { Log.d("Loki", "Can't leave nonexistent closed group.") return@queue deferred.reject(Error.NoThread) } // Send the update to the group @Suppress("NAME_SHADOWING") - val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, ClosedGroupUpdateMessageSendJobV2.Kind.Leave) + val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, ClosedGroupUpdateMessageSendJobV2.Kind.Leave, sentTime) job.setContext(context) job.onRun() // Run the job immediately // Remove the group private key and unsubscribe from PNs @@ -116,7 +119,7 @@ object ClosedGroupsProtocolV2 { // Notify the user val infoType = GroupContext.Type.QUIT val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID) + insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime) deferred.resolve(Unit) } return deferred.promise @@ -140,6 +143,7 @@ object ClosedGroupsProtocolV2 { val newMembersAsData = membersToAdd.map { Hex.fromStringCondensed(it) } val admins = group.admins.map { it.serialize() } val adminsAsData = admins.map { Hex.fromStringCondensed(it) } + val sentTime = System.currentTimeMillis() val encryptionKeyPair = apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) if (encryptionKeyPair == null) { Log.d("Loki", "Couldn't get encryption key pair for closed group.") @@ -148,7 +152,7 @@ object ClosedGroupsProtocolV2 { val name = group.title // Send the update to the group val memberUpdateKind = ClosedGroupUpdateMessageSendJobV2.Kind.AddMembers(newMembersAsData) - val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, memberUpdateKind) + val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, memberUpdateKind, sentTime) job.setContext(context) job.onRun() // Run the job immediately // Send closed group update messages to any new members individually @@ -156,13 +160,13 @@ object ClosedGroupsProtocolV2 { @Suppress("NAME_SHADOWING") val closedGroupNewKind = ClosedGroupUpdateMessageSendJobV2.Kind.New(Hex.fromStringCondensed(groupPublicKey), name, encryptionKeyPair, membersAsData, adminsAsData) @Suppress("NAME_SHADOWING") - val newMemberJob = ClosedGroupUpdateMessageSendJobV2(member, closedGroupNewKind) + val newMemberJob = ClosedGroupUpdateMessageSendJobV2(member, closedGroupNewKind, sentTime) ApplicationContext.getInstance(context).jobManager.add(newMemberJob) } // Notify the user val infoType = GroupContext.Type.UPDATE val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID) + insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime) } } @@ -183,6 +187,7 @@ object ClosedGroupsProtocolV2 { groupDB.updateMembers(groupID, updatedMembers.map { Address.fromSerialized(it) }) val removeMembersAsData = membersToRemove.map { Hex.fromStringCondensed(it) } val admins = group.admins.map { it.serialize() } + val sentTime = System.currentTimeMillis() val encryptionKeyPair = apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) if (encryptionKeyPair == null) { Log.d("Loki", "Couldn't get encryption key pair for closed group.") @@ -195,7 +200,7 @@ object ClosedGroupsProtocolV2 { val name = group.title // Send the update to the group val memberUpdateKind = ClosedGroupUpdateMessageSendJobV2.Kind.RemoveMembers(removeMembersAsData) - val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, memberUpdateKind) + val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, memberUpdateKind, sentTime) job.setContext(context) job.onRun() // Run the job immediately val isCurrentUserAdmin = admins.contains(userPublicKey) @@ -205,7 +210,7 @@ object ClosedGroupsProtocolV2 { // Notify the user val infoType = GroupContext.Type.UPDATE val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID) + insertOutgoingInfoMessage(context, groupID, infoType, name, updatedMembers, admins, threadID, sentTime) } } @@ -218,13 +223,14 @@ object ClosedGroupsProtocolV2 { val group = groupDB.getGroup(groupID).orNull() val members = group.members.map { it.serialize() }.toSet() val admins = group.admins.map { it.serialize() } + val sentTime = System.currentTimeMillis() if (group == null) { Log.d("Loki", "Can't leave nonexistent closed group.") return@queue deferred.reject(Error.NoThread) } // Send the update to the group val kind = ClosedGroupUpdateMessageSendJobV2.Kind.NameChange(newName) - val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, kind) + val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, kind, sentTime) job.setContext(context) job.onRun() // Run the job immediately // Update the group @@ -232,7 +238,7 @@ object ClosedGroupsProtocolV2 { // Notify the user val infoType = GroupContext.Type.UPDATE val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, infoType, newName, members, admins, threadID) + insertOutgoingInfoMessage(context, groupID, infoType, newName, members, admins, threadID, sentTime) deferred.resolve(Unit) } return deferred.promise @@ -272,6 +278,7 @@ object ClosedGroupsProtocolV2 { Log.d("Loki", "Can't update nonexistent closed group.") return@queue deferred.reject(Error.NoThread) } + val sentTime = System.currentTimeMillis() val oldMembers = group.members.map { it.serialize() }.toSet() val newMembers = members.minus(oldMembers) val membersAsData = members.map { Hex.fromStringCondensed(it) } @@ -298,7 +305,7 @@ object ClosedGroupsProtocolV2 { @Suppress("NAME_SHADOWING") val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJobV2.Kind.Update(name, membersAsData) @Suppress("NAME_SHADOWING") - val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, closedGroupUpdateKind) + val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, closedGroupUpdateKind, sentTime) job.setContext(context) job.onRun() // Run the job immediately if (isUserLeaving) { @@ -322,7 +329,7 @@ object ClosedGroupsProtocolV2 { @Suppress("NAME_SHADOWING") val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJobV2.Kind.New(Hex.fromStringCondensed(groupPublicKey), name, encryptionKeyPair, membersAsData, adminsAsData) @Suppress("NAME_SHADOWING") - val job = ClosedGroupUpdateMessageSendJobV2(member, closedGroupUpdateKind) + val job = ClosedGroupUpdateMessageSendJobV2(member, closedGroupUpdateKind, sentTime) ApplicationContext.getInstance(context).jobManager.add(job) } } @@ -335,7 +342,7 @@ object ClosedGroupsProtocolV2 { // Notify the user val infoType = if (isUserLeaving) GroupContext.Type.QUIT else GroupContext.Type.UPDATE val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, infoType, name, members, admins, threadID) + insertOutgoingInfoMessage(context, groupID, infoType, name, members, admins, threadID, sentTime) deferred.resolve(Unit) } return deferred.promise @@ -367,7 +374,7 @@ object ClosedGroupsProtocolV2 { val ciphertext = SessionProtocolImpl(context).encrypt(plaintext, publicKey) ClosedGroupUpdateMessageSendJobV2.KeyPairWrapper(publicKey, ciphertext) } - val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, ClosedGroupUpdateMessageSendJobV2.Kind.EncryptionKeyPair(wrappers)) + val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, ClosedGroupUpdateMessageSendJobV2.Kind.EncryptionKeyPair(wrappers), System.currentTimeMillis()) job.setContext(context) job.onRun() // Run the job immediately // Store it * after * having sent out the message to the group @@ -376,9 +383,9 @@ object ClosedGroupsProtocolV2 { @JvmStatic fun handleMessage(context: Context, closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) { - if (!isValid(closedGroupUpdate, senderPublicKey)) { return } + if (!isValid(context, closedGroupUpdate, senderPublicKey, sentTimestamp)) { return } when (closedGroupUpdate.type) { - SignalServiceProtos.ClosedGroupUpdateV2.Type.NEW -> handleNewClosedGroup(context, closedGroupUpdate, senderPublicKey) + SignalServiceProtos.ClosedGroupUpdateV2.Type.NEW -> handleNewClosedGroup(context, closedGroupUpdate, senderPublicKey, sentTimestamp) SignalServiceProtos.ClosedGroupUpdateV2.Type.MEMBERS_REMOVED -> handleClosedGroupMembersRemoved(context, closedGroupUpdate, sentTimestamp, groupPublicKey, senderPublicKey) SignalServiceProtos.ClosedGroupUpdateV2.Type.MEMBERS_ADDED -> handleClosedGroupMembersAdded(context, closedGroupUpdate, sentTimestamp, groupPublicKey, senderPublicKey) SignalServiceProtos.ClosedGroupUpdateV2.Type.NAME_CHANGE -> handleClosedGroupNameChange(context, closedGroupUpdate, sentTimestamp, groupPublicKey, senderPublicKey) @@ -391,7 +398,10 @@ object ClosedGroupsProtocolV2 { } } - private fun isValid(closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, senderPublicKey: String): Boolean { + private fun isValid(context: Context, closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, senderPublicKey: String, sentTimestamp: Long): Boolean { + val record = DatabaseFactory.getMmsSmsDatabase(context).getMessageFor(sentTimestamp, senderPublicKey) + if (record != null) return false + return when (closedGroupUpdate.type) { SignalServiceProtos.ClosedGroupUpdateV2.Type.NEW -> { (!closedGroupUpdate.publicKey.isEmpty && !closedGroupUpdate.name.isNullOrEmpty() && !(closedGroupUpdate.encryptionKeyPair.privateKey ?: ByteString.copyFrom(ByteArray(0))).isEmpty @@ -413,7 +423,7 @@ object ClosedGroupsProtocolV2 { } } - public fun handleNewClosedGroup(context: Context, closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, senderPublicKey: String) { + public fun handleNewClosedGroup(context: Context, closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, senderPublicKey: String, sentTimestamp: Long) { // Prepare val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! val apiDB = DatabaseFactory.getLokiAPIDatabase(context) @@ -426,7 +436,8 @@ object ClosedGroupsProtocolV2 { // Create the group val groupID = doubleEncodeGroupID(groupPublicKey) val groupDB = DatabaseFactory.getGroupDatabase(context) - if (groupDB.getGroup(groupID).orNull() != null) { + val prevGroup = groupDB.getGroup(groupID).orNull() + if (prevGroup != null) { // Update the group groupDB.updateTitle(groupID, name) groupDB.updateMembers(groupID, members.map { Address.fromSerialized(it) }) @@ -440,8 +451,14 @@ object ClosedGroupsProtocolV2 { // Store the encryption key pair val encryptionKeyPair = ECKeyPair(DjbECPublicKey(encryptionKeyPairAsProto.publicKey.toByteArray().removing05PrefixIfNeeded()), DjbECPrivateKey(encryptionKeyPairAsProto.privateKey.toByteArray())) apiDB.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey) - // Notify the user - insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) + // Notify the user (if we didn't make the group) + if (userPublicKey != senderPublicKey) { + insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) + } else if (prevGroup == null) { + // only notify if we created this group + val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) + insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp) + } // Notify the PN server LokiPushNotificationManager.performOperation(context, ClosedGroupOperation.Subscribe, groupPublicKey, userPublicKey) } @@ -451,8 +468,8 @@ object ClosedGroupsProtocolV2 { val groupDB = DatabaseFactory.getGroupDatabase(context) val groupID = doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() - if (group == null) { - Log.d("Loki", "Ignoring closed group info message for nonexistent group.") + if (group == null || !group.isActive) { + Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") return } val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! @@ -491,16 +508,21 @@ object ClosedGroupsProtocolV2 { val (contextType, signalType) = if (senderLeft) GroupContext.Type.QUIT to SignalServiceGroup.Type.QUIT else GroupContext.Type.UPDATE to SignalServiceGroup.Type.UPDATE - - insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins) + if (userPublicKey == senderPublicKey) { + val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) + insertOutgoingInfoMessage(context, groupID, contextType, name, members, admins, threadID, sentTimestamp) + } else { + insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins) + } } fun handleClosedGroupMembersAdded(context: Context, closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) { + val userPublicKey = TextSecurePreferences.getLocalNumber(context) val groupDB = DatabaseFactory.getGroupDatabase(context) val groupID = doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() - if (group == null) { - Log.d("Loki", "Ignoring closed group info message for nonexistent group.") + if (group == null || !group.isActive) { + Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") return } if (!isValidGroupUpdate(group, sentTimestamp, senderPublicKey)) { @@ -517,16 +539,22 @@ object ClosedGroupsProtocolV2 { val newMembers = members + updateMembers groupDB.updateMembers(groupID, newMembers.map { Address.fromSerialized(it) }) - insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) + if (userPublicKey == senderPublicKey) { + val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) + insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp) + } else { + insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) + } } fun handleClosedGroupNameChange(context: Context, closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) { // Check that the sender is a member of the group (before the update) + val userPublicKey = TextSecurePreferences.getLocalNumber(context) val groupDB = DatabaseFactory.getGroupDatabase(context) val groupID = doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() - if (group == null) { - Log.d("Loki", "Ignoring closed group info message for nonexistent group.") + if (group == null || !group.isActive) { + Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") return } // Check common group update logic @@ -538,21 +566,23 @@ object ClosedGroupsProtocolV2 { val name = closedGroupUpdate.name groupDB.updateTitle(groupID, name) - insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) + if (userPublicKey == senderPublicKey) { + val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) + insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp) + } else { + insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) + } } private fun handleClosedGroupMemberLeft(context: Context, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) { // Check the user leaving isn't us, will already be handled val userPublicKey = TextSecurePreferences.getLocalNumber(context)!! - if (senderPublicKey == userPublicKey) { - return - } val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context) val groupID = doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() - if (group == null) { - Log.d("Loki", "Ignoring closed group info message for nonexistent group.") + if (group == null || !group.isActive) { + Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") return } val name = group.title @@ -575,7 +605,12 @@ object ClosedGroupsProtocolV2 { generateAndSendNewEncryptionKeyPair(context, groupPublicKey, updatedMemberList) } } - insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.QUIT, SignalServiceGroup.Type.QUIT, name, members, admins) + if (userPublicKey == senderPublicKey) { + val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) + insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID, sentTimestamp) + } else { + insertIncomingInfoMessage(context, senderPublicKey, groupID, GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) + } } private fun handleClosedGroupUpdate(context: Context, closedGroupUpdate: SignalServiceProtos.ClosedGroupUpdateV2, sentTimestamp: Long, groupPublicKey: String, senderPublicKey: String) { @@ -588,8 +623,8 @@ object ClosedGroupsProtocolV2 { val groupDB = DatabaseFactory.getGroupDatabase(context) val groupID = doubleEncodeGroupID(groupPublicKey) val group = groupDB.getGroup(groupID).orNull() - if (group == null) { - Log.d("Loki", "Ignoring closed group info message for nonexistent group.") + if (group == null || !group.isActive) { + Log.d("Loki", "Ignoring closed group info message for nonexistent or inactive group.") return } val oldMembers = group.members.map { it.serialize() } @@ -623,7 +658,13 @@ object ClosedGroupsProtocolV2 { val wasSenderRemoved = !members.contains(senderPublicKey) val type0 = if (wasSenderRemoved) GroupContext.Type.QUIT else GroupContext.Type.UPDATE val type1 = if (wasSenderRemoved) SignalServiceGroup.Type.QUIT else SignalServiceGroup.Type.UPDATE - insertIncomingInfoMessage(context, senderPublicKey, groupID, type0, type1, name, members, group.admins.map { it.toString() }) + val admins = group.admins.map { it.toString() } + if (userPublicKey == senderPublicKey) { + val threadID = DatabaseFactory.getLokiThreadDatabase(context).getThreadID(groupID) + insertOutgoingInfoMessage(context, groupID, type0, name, members, admins, threadID, sentTimestamp) + } else { + insertIncomingInfoMessage(context, senderPublicKey, groupID, type0, type1, name, members, admins) + } } private fun disableLocalGroupAndUnsubscribe(context: Context, apiDB: LokiAPIDatabase, groupPublicKey: String, groupDB: GroupDatabase, groupID: String, userPublicKey: String) { @@ -699,7 +740,8 @@ object ClosedGroupsProtocolV2 { } private fun insertOutgoingInfoMessage(context: Context, groupID: String, type: GroupContext.Type, name: String, - members: Collection, admins: Collection, threadID: Long) { + members: Collection, admins: Collection, threadID: Long, + sentTime: Long) { val recipient = Recipient.from(context, Address.fromSerialized(groupID), false) val groupContextBuilder = GroupContext.newBuilder() .setId(ByteString.copyFrom(GroupUtil.getDecodedGroupIDAsData(groupID))) @@ -707,9 +749,9 @@ object ClosedGroupsProtocolV2 { .setName(name) .addAllMembers(members) .addAllAdmins(admins) - val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, System.currentTimeMillis(), 0, null, listOf(), listOf()) + val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, 0, null, listOf(), listOf()) val mmsDB = DatabaseFactory.getMmsDatabase(context) - val infoMessageID = mmsDB.insertMessageOutbox(infoMessage, threadID, false, null) + val infoMessageID = mmsDB.insertMessageOutbox(infoMessage, threadID, false, null, sentTime) mmsDB.markAsSent(infoMessageID, true) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingGroupMediaMessage.java b/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingGroupMediaMessage.java index d34a14909c..4b1fbfb257 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingGroupMediaMessage.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingGroupMediaMessage.java @@ -40,7 +40,6 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage { public OutgoingGroupMediaMessage(@NonNull Recipient recipient, @NonNull GroupContext group, @Nullable final Attachment avatar, - long sentTimeMillis, long expireIn, @Nullable QuoteModel quote, @NonNull List contacts, diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java b/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java index 263b9276bf..be28948a3c 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java @@ -1052,7 +1052,6 @@ public class SignalServiceMessageSender { Optional syncTarget) throws IOException, UntrustedIdentityException { - if (recipient.getNumber().equals(userPublicKey) && !syncTarget.isPresent()) { return SendMessageResult.success(recipient, false, false); } final SettableFuture[] future = { new SettableFuture() }; OutgoingPushMessageList messages = getSessionProtocolEncryptedMessage(recipient, timestamp, content); // Loki - Remove this when we have shared sender keys