X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/d267974223294b9ac08491999d8f2bece2b80c54..4f2261e86f493a9c8954c02c52ddaa9a46490d20:/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java diff --git a/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java b/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java new file mode 100644 index 00000000..5a9ffb9c --- /dev/null +++ b/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java @@ -0,0 +1,106 @@ +package org.asamk.signal.manager.helper; + +import org.asamk.signal.storage.groups.GroupInfo; +import org.asamk.signal.storage.groups.GroupInfoV1; +import org.asamk.signal.storage.groups.GroupInfoV2; +import org.signal.storageservice.protos.groups.Member; +import org.signal.zkgroup.groups.GroupSecretParams; +import org.signal.zkgroup.profiles.ProfileKeyCredential; +import org.whispersystems.libsignal.util.guava.Optional; +import org.whispersystems.signalservice.api.groupsv2.GroupCandidate; +import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations; +import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; +import org.whispersystems.signalservice.api.messages.SignalServiceGroup; +import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2; +import org.whispersystems.signalservice.api.push.SignalServiceAddress; + +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +public class GroupHelper { + + private final ProfileKeyCredentialProvider profileKeyCredentialProvider; + + private final ProfileProvider profileProvider; + + private final SelfAddressProvider selfAddressProvider; + + private final GroupsV2Operations groupsV2Operations; + + public GroupHelper( + final ProfileKeyCredentialProvider profileKeyCredentialProvider, + final ProfileProvider profileProvider, + final SelfAddressProvider selfAddressProvider, + final GroupsV2Operations groupsV2Operations + ) { + this.profileKeyCredentialProvider = profileKeyCredentialProvider; + this.profileProvider = profileProvider; + this.selfAddressProvider = selfAddressProvider; + this.groupsV2Operations = groupsV2Operations; + } + + public static void setGroupContext( + final SignalServiceDataMessage.Builder messageBuilder, final GroupInfo groupInfo + ) { + if (groupInfo instanceof GroupInfoV1) { + SignalServiceGroup group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.DELIVER) + .withId(groupInfo.groupId) + .build(); + messageBuilder.asGroupMessage(group); + } else { + final GroupInfoV2 groupInfoV2 = (GroupInfoV2) groupInfo; + SignalServiceGroupV2 group = SignalServiceGroupV2.newBuilder(groupInfoV2.getMasterKey()) + .withRevision(groupInfoV2.getGroup() == null ? 0 : groupInfoV2.getGroup().getRevision()) + .build(); + messageBuilder.asGroupMessage(group); + } + } + + public GroupsV2Operations.NewGroup createGroupV2( + String name, Collection members, byte[] avatar + ) { + final ProfileKeyCredential profileKeyCredential = profileKeyCredentialProvider.getProfileKeyCredential( + selfAddressProvider.getSelfAddress()); + if (profileKeyCredential == null) { + System.err.println("Cannot create a V2 group as self does not have a versioned profile"); + return null; + } + + final int noUuidCapability = members.stream() + .filter(address -> !address.getUuid().isPresent()) + .collect(Collectors.toUnmodifiableSet()) + .size(); + if (noUuidCapability > 0) { + System.err.println("Cannot create a V2 group as " + noUuidCapability + " members don't have a UUID."); + return null; + } + + final int noGv2Capability = members.stream() + .map(profileProvider::getProfile) + .filter(profile -> !profile.getCapabilities().gv2) + .collect(Collectors.toUnmodifiableSet()) + .size(); + if (noGv2Capability > 0) { + System.err.println("Cannot create a V2 group as " + noGv2Capability + " members don't support Groups V2."); + return null; + } + + GroupCandidate self = new GroupCandidate(selfAddressProvider.getSelfAddress().getUuid().orNull(), + Optional.fromNullable(profileKeyCredential)); + Set candidates = members.stream() + .map(member -> new GroupCandidate(member.getUuid().get(), + Optional.fromNullable(profileKeyCredentialProvider.getProfileKeyCredential(member)))) + .collect(Collectors.toSet()); + + final GroupSecretParams groupSecretParams = GroupSecretParams.generate(); + return groupsV2Operations.createNewGroup(groupSecretParams, + name, + Optional.fromNullable(avatar), + self, + candidates, + Member.Role.DEFAULT, + 0); + } + +}