2014-02-03 04:38:06 +01:00
|
|
|
package org.thoughtcrime.securesms.util;
|
|
|
|
|
2014-12-15 15:44:41 +01:00
|
|
|
import android.content.Context;
|
2019-09-07 05:40:06 +02:00
|
|
|
|
2019-06-05 21:47:14 +02:00
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import androidx.annotation.WorkerThread;
|
2018-09-10 17:40:00 +02:00
|
|
|
|
2020-10-06 16:24:14 +02:00
|
|
|
import org.signal.zkgroup.InvalidInputException;
|
|
|
|
import org.signal.zkgroup.groups.GroupMasterKey;
|
2015-09-17 02:31:24 +02:00
|
|
|
import org.thoughtcrime.securesms.R;
|
2018-09-10 17:40:00 +02:00
|
|
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
|
|
|
import org.thoughtcrime.securesms.database.GroupDatabase;
|
2020-04-20 17:01:31 +02:00
|
|
|
import org.thoughtcrime.securesms.groups.BadGroupIdException;
|
2020-03-26 15:00:17 +01:00
|
|
|
import org.thoughtcrime.securesms.groups.GroupId;
|
2018-08-01 17:09:24 +02:00
|
|
|
import org.thoughtcrime.securesms.logging.Log;
|
2020-05-13 18:36:57 +02:00
|
|
|
import org.thoughtcrime.securesms.mms.MessageGroupContext;
|
2016-04-05 16:33:40 +02:00
|
|
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
2020-05-11 17:33:45 +02:00
|
|
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
2018-09-10 17:40:00 +02:00
|
|
|
import org.whispersystems.libsignal.util.guava.Optional;
|
2020-04-20 18:41:03 +02:00
|
|
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
|
|
|
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
|
2020-03-27 19:12:10 +01:00
|
|
|
import org.whispersystems.signalservice.api.messages.SignalServiceGroupContext;
|
2020-04-20 18:41:03 +02:00
|
|
|
import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2;
|
2014-02-17 20:42:51 +01:00
|
|
|
|
2014-02-03 04:38:06 +01:00
|
|
|
import java.io.IOException;
|
2017-07-26 18:59:15 +02:00
|
|
|
import java.util.List;
|
2014-02-03 04:38:06 +01:00
|
|
|
|
2020-03-26 15:00:17 +01:00
|
|
|
public final class GroupUtil {
|
2014-02-03 04:38:06 +01:00
|
|
|
|
2020-03-26 15:00:17 +01:00
|
|
|
private GroupUtil() {
|
2014-02-03 04:38:06 +01:00
|
|
|
}
|
|
|
|
|
2020-03-26 15:00:17 +01:00
|
|
|
private static final String TAG = Log.tag(GroupUtil.class);
|
2014-02-03 04:38:06 +01:00
|
|
|
|
2020-03-27 19:12:10 +01:00
|
|
|
/**
|
|
|
|
* Result may be a v1 or v2 GroupId.
|
|
|
|
*/
|
2020-04-20 17:01:31 +02:00
|
|
|
public static @NonNull GroupId idFromGroupContext(@NonNull SignalServiceGroupContext groupContext)
|
|
|
|
throws BadGroupIdException
|
|
|
|
{
|
2020-03-27 19:12:10 +01:00
|
|
|
if (groupContext.getGroupV1().isPresent()) {
|
2020-09-10 19:39:29 +02:00
|
|
|
return GroupId.v1Exact(groupContext.getGroupV1().get().getGroupId());
|
2020-03-27 19:12:10 +01:00
|
|
|
} else if (groupContext.getGroupV2().isPresent()) {
|
|
|
|
return GroupId.v2(groupContext.getGroupV2().get().getMasterKey());
|
|
|
|
} else {
|
|
|
|
throw new AssertionError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-20 17:01:31 +02:00
|
|
|
public static @NonNull GroupId idFromGroupContextOrThrow(@NonNull SignalServiceGroupContext groupContext) {
|
|
|
|
try {
|
|
|
|
return idFromGroupContext(groupContext);
|
|
|
|
} catch (BadGroupIdException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-27 19:12:10 +01:00
|
|
|
/**
|
|
|
|
* Result may be a v1 or v2 GroupId.
|
|
|
|
*/
|
2020-04-20 17:01:31 +02:00
|
|
|
public static @NonNull Optional<GroupId> idFromGroupContext(@NonNull Optional<SignalServiceGroupContext> groupContext)
|
|
|
|
throws BadGroupIdException
|
|
|
|
{
|
|
|
|
if (groupContext.isPresent()) {
|
|
|
|
return Optional.of(idFromGroupContext(groupContext.get()));
|
|
|
|
}
|
|
|
|
return Optional.absent();
|
2020-03-27 19:12:10 +01:00
|
|
|
}
|
|
|
|
|
2020-10-06 16:24:14 +02:00
|
|
|
public static @NonNull GroupMasterKey requireMasterKey(@NonNull byte[] masterKey) {
|
|
|
|
try {
|
|
|
|
return new GroupMasterKey(masterKey);
|
|
|
|
} catch (InvalidInputException e) {
|
|
|
|
throw new AssertionError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-24 17:35:44 +02:00
|
|
|
public static @NonNull GroupDescription getNonV2GroupDescription(@NonNull Context context, @Nullable String encodedGroup) {
|
2014-02-22 02:51:25 +01:00
|
|
|
if (encodedGroup == null) {
|
2015-09-17 02:31:24 +02:00
|
|
|
return new GroupDescription(context, null);
|
2014-02-22 02:51:25 +01:00
|
|
|
}
|
2014-02-18 07:20:43 +01:00
|
|
|
|
2014-02-22 02:51:25 +01:00
|
|
|
try {
|
2020-07-24 17:35:44 +02:00
|
|
|
MessageGroupContext groupContext = new MessageGroupContext(encodedGroup, false);
|
2015-09-17 02:31:24 +02:00
|
|
|
return new GroupDescription(context, groupContext);
|
|
|
|
} catch (IOException e) {
|
|
|
|
Log.w(TAG, e);
|
|
|
|
return new GroupDescription(context, null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-20 18:41:03 +02:00
|
|
|
@WorkerThread
|
|
|
|
public static void setDataMessageGroupContext(@NonNull Context context,
|
|
|
|
@NonNull SignalServiceDataMessage.Builder dataMessageBuilder,
|
|
|
|
@NonNull GroupId.Push groupId)
|
|
|
|
{
|
|
|
|
if (groupId.isV2()) {
|
|
|
|
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
|
|
|
GroupDatabase.GroupRecord groupRecord = groupDatabase.requireGroup(groupId);
|
|
|
|
GroupDatabase.V2GroupProperties v2GroupProperties = groupRecord.requireV2GroupProperties();
|
|
|
|
SignalServiceGroupV2 group = SignalServiceGroupV2.newBuilder(v2GroupProperties.getGroupMasterKey())
|
|
|
|
.withRevision(v2GroupProperties.getGroupRevision())
|
|
|
|
.build();
|
|
|
|
dataMessageBuilder.asGroupMessage(group);
|
|
|
|
} else {
|
|
|
|
dataMessageBuilder.asGroupMessage(new SignalServiceGroup(groupId.getDecodedId()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-17 02:31:24 +02:00
|
|
|
public static class GroupDescription {
|
|
|
|
|
2020-05-13 18:36:57 +02:00
|
|
|
@NonNull private final Context context;
|
|
|
|
@Nullable private final MessageGroupContext groupContext;
|
|
|
|
@Nullable private final List<RecipientId> members;
|
2015-09-17 02:31:24 +02:00
|
|
|
|
2020-05-13 18:36:57 +02:00
|
|
|
GroupDescription(@NonNull Context context, @Nullable MessageGroupContext groupContext) {
|
2015-09-17 02:31:24 +02:00
|
|
|
this.context = context.getApplicationContext();
|
|
|
|
this.groupContext = groupContext;
|
|
|
|
|
2020-05-13 18:36:57 +02:00
|
|
|
if (groupContext == null) {
|
2015-09-17 02:31:24 +02:00
|
|
|
this.members = null;
|
|
|
|
} else {
|
2020-05-13 18:36:57 +02:00
|
|
|
List<RecipientId> membersList = groupContext.getMembersListExcludingSelf();
|
|
|
|
this.members = membersList.isEmpty() ? null : membersList;
|
2015-09-17 02:31:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-24 17:35:44 +02:00
|
|
|
@WorkerThread
|
|
|
|
public String toString(@NonNull Recipient sender) {
|
2016-04-05 16:33:40 +02:00
|
|
|
StringBuilder description = new StringBuilder();
|
2020-06-16 16:37:27 +02:00
|
|
|
description.append(context.getString(R.string.MessageRecord_s_updated_group, sender.getDisplayName(context)));
|
2016-04-05 16:33:40 +02:00
|
|
|
|
2015-09-17 02:31:24 +02:00
|
|
|
if (groupContext == null) {
|
2016-04-05 16:33:40 +02:00
|
|
|
return description.toString();
|
2015-09-17 02:31:24 +02:00
|
|
|
}
|
2014-02-17 20:42:51 +01:00
|
|
|
|
2020-07-29 06:55:20 +02:00
|
|
|
String title = StringUtil.isolateBidi(groupContext.getName());
|
2015-09-17 02:31:24 +02:00
|
|
|
|
2020-01-07 00:36:56 +01:00
|
|
|
if (members != null && members.size() > 0) {
|
2016-04-05 16:33:40 +02:00
|
|
|
description.append("\n");
|
2015-11-14 13:30:33 +01:00
|
|
|
description.append(context.getResources().getQuantityString(R.plurals.GroupUtil_joined_the_group,
|
2017-08-01 17:56:00 +02:00
|
|
|
members.size(), toString(members)));
|
2014-02-22 02:51:25 +01:00
|
|
|
}
|
2014-02-17 20:42:51 +01:00
|
|
|
|
2020-07-31 05:05:09 +02:00
|
|
|
if (!title.trim().isEmpty()) {
|
2016-04-05 16:33:40 +02:00
|
|
|
if (members != null) description.append(" ");
|
|
|
|
else description.append("\n");
|
2015-06-13 23:16:02 +02:00
|
|
|
description.append(context.getString(R.string.GroupUtil_group_name_is_now, title));
|
2014-02-22 02:51:25 +01:00
|
|
|
}
|
2014-02-15 00:59:57 +01:00
|
|
|
|
2016-04-05 16:33:40 +02:00
|
|
|
return description.toString();
|
2015-09-17 02:31:24 +02:00
|
|
|
}
|
|
|
|
|
2020-05-11 17:33:45 +02:00
|
|
|
private String toString(List<RecipientId> recipients) {
|
|
|
|
StringBuilder result = new StringBuilder();
|
2017-08-01 17:56:00 +02:00
|
|
|
|
2020-05-11 17:33:45 +02:00
|
|
|
for (int i = 0; i < recipients.size(); i++) {
|
2020-06-16 16:37:27 +02:00
|
|
|
result.append(Recipient.live(recipients.get(i)).get().getDisplayName(context));
|
2017-08-01 17:56:00 +02:00
|
|
|
|
|
|
|
if (i != recipients.size() -1 )
|
2020-05-11 17:33:45 +02:00
|
|
|
result.append(", ");
|
2017-08-01 17:56:00 +02:00
|
|
|
}
|
|
|
|
|
2020-05-11 17:33:45 +02:00
|
|
|
return result.toString();
|
2017-08-01 17:56:00 +02:00
|
|
|
}
|
2014-02-15 00:59:57 +01:00
|
|
|
}
|
2014-02-03 04:38:06 +01:00
|
|
|
}
|