Fix message syncing in group chats

This commit is contained in:
Mikunj 2020-02-04 10:09:32 +11:00
parent f7b2312f99
commit cc369f5c52
1 changed files with 35 additions and 8 deletions

View File

@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
@ -35,6 +36,7 @@ import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.SignalProtocolAddress;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
@ -56,6 +58,7 @@ import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@ -163,8 +166,13 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
else if (!existingNetworkFailures.isEmpty()) target = Stream.of(existingNetworkFailures).map(NetworkFailure::getAddress).toList();
else target = getGroupMessageRecipients(message.getRecipient().getAddress().toGroupString(), messageId);
String localNumber = TextSecurePreferences.getLocalNumber(context);
// Only send messages to the contacts we have sessions with
List<Address> validTargets = Stream.of(target).filter(member -> {
// Our device is always valid
if (member.serialize().equalsIgnoreCase(localNumber)) { return true; }
SignalProtocolAddress protocolAddress = new SignalProtocolAddress(member.toPhoneString(), SignalServiceAddress.DEFAULT_DEVICE_ID);
boolean hasSession = new TextSecureSessionStore(context).containsSession(protocolAddress);
if (hasSession) { return true; }
@ -330,18 +338,37 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
}
return result;
} else {
/*
Our biggest assumption here is that group members will only consist of primary devices.
No secondary device should be able to be added to a group.
*/
List<GroupReceiptInfo> destinations = DatabaseFactory.getGroupReceiptDatabase(context).getGroupReceiptInfo(messageId);
if (!destinations.isEmpty()) return Stream.of(destinations).map(GroupReceiptInfo::getAddress).toList();
List<Recipient> members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
Set<Address> memberSet = new HashSet<>();
if (destinations.isEmpty()) {
List<Recipient> groupMembers = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
memberSet.addAll(Stream.of(groupMembers).map(Recipient::getAddress).toList());
} else {
memberSet.addAll(Stream.of(destinations).map(GroupReceiptInfo::getAddress).toList());
}
// Add secondary devices to the list
Set<Address> memberSet = Stream.of(members).map(Recipient::getAddress).collect(Collectors.toSet());
for (Recipient member : members) {
if (!member.getAddress().isPhone()) { continue; }
// Replace primary device public key with ours so message syncing works correctly
String masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
String localNumber = TextSecurePreferences.getLocalNumber(context);
if (masterHexEncodedPublicKey != null && memberSet.contains(Address.fromSerialized(masterHexEncodedPublicKey))) {
memberSet.remove(Address.fromSerialized(masterHexEncodedPublicKey));
memberSet.add(Address.fromSerialized(localNumber));
}
// Add secondary devices to the list. We shouldn't add our secondary devices
for (Address member : memberSet) {
if (!member.isPhone() || member.serialize().equalsIgnoreCase(localNumber)) { continue; }
try {
List<String> secondaryDevices = PromiseUtil.timeout(LokiStorageAPI.shared.getSecondaryDevicePublicKeys(member.getAddress().serialize()), 5000).get();
memberSet.addAll(Stream.of(secondaryDevices).map(Address::fromSerialized).toList());
List<String> secondaryDevices = PromiseUtil.timeout(LokiStorageAPI.shared.getSecondaryDevicePublicKeys(member.serialize()), 5000).get();
memberSet.addAll(Stream.of(secondaryDevices).map(string -> {
// Loki - Calling .map(Address::fromSerialized) is causing errors, thus we use the long method :(
return Address.fromSerialized(string);
}).toList());
} catch (Exception e) {
// Timed out, go to the next member
}