1 package org
.asamk
.signal
.manager
.helper
;
3 import org
.asamk
.signal
.storage
.groups
.GroupInfo
;
4 import org
.asamk
.signal
.storage
.groups
.GroupInfoV1
;
5 import org
.asamk
.signal
.storage
.groups
.GroupInfoV2
;
6 import org
.signal
.storageservice
.protos
.groups
.Member
;
7 import org
.signal
.zkgroup
.groups
.GroupSecretParams
;
8 import org
.signal
.zkgroup
.profiles
.ProfileKeyCredential
;
9 import org
.whispersystems
.libsignal
.util
.guava
.Optional
;
10 import org
.whispersystems
.signalservice
.api
.groupsv2
.GroupCandidate
;
11 import org
.whispersystems
.signalservice
.api
.groupsv2
.GroupsV2Operations
;
12 import org
.whispersystems
.signalservice
.api
.messages
.SignalServiceDataMessage
;
13 import org
.whispersystems
.signalservice
.api
.messages
.SignalServiceGroup
;
14 import org
.whispersystems
.signalservice
.api
.messages
.SignalServiceGroupV2
;
15 import org
.whispersystems
.signalservice
.api
.push
.SignalServiceAddress
;
17 import java
.util
.Collection
;
19 import java
.util
.stream
.Collectors
;
21 public class GroupHelper
{
23 private final ProfileKeyCredentialProvider profileKeyCredentialProvider
;
25 private final ProfileProvider profileProvider
;
27 private final SelfAddressProvider selfAddressProvider
;
29 private final GroupsV2Operations groupsV2Operations
;
32 final ProfileKeyCredentialProvider profileKeyCredentialProvider
,
33 final ProfileProvider profileProvider
,
34 final SelfAddressProvider selfAddressProvider
,
35 final GroupsV2Operations groupsV2Operations
37 this.profileKeyCredentialProvider
= profileKeyCredentialProvider
;
38 this.profileProvider
= profileProvider
;
39 this.selfAddressProvider
= selfAddressProvider
;
40 this.groupsV2Operations
= groupsV2Operations
;
43 public static void setGroupContext(
44 final SignalServiceDataMessage
.Builder messageBuilder
, final GroupInfo groupInfo
46 if (groupInfo
instanceof GroupInfoV1
) {
47 SignalServiceGroup group
= SignalServiceGroup
.newBuilder(SignalServiceGroup
.Type
.DELIVER
)
48 .withId(groupInfo
.groupId
)
50 messageBuilder
.asGroupMessage(group
);
52 final GroupInfoV2 groupInfoV2
= (GroupInfoV2
) groupInfo
;
53 SignalServiceGroupV2 group
= SignalServiceGroupV2
.newBuilder(groupInfoV2
.getMasterKey())
54 .withRevision(groupInfoV2
.getGroup() == null ?
0 : groupInfoV2
.getGroup().getRevision())
56 messageBuilder
.asGroupMessage(group
);
60 public GroupsV2Operations
.NewGroup
createGroupV2(
61 String name
, Collection
<SignalServiceAddress
> members
, byte[] avatar
63 final ProfileKeyCredential profileKeyCredential
= profileKeyCredentialProvider
.getProfileKeyCredential(
64 selfAddressProvider
.getSelfAddress());
65 if (profileKeyCredential
== null) {
66 System
.err
.println("Cannot create a V2 group as self does not have a versioned profile");
70 final int noUuidCapability
= members
.stream()
71 .filter(address
-> !address
.getUuid().isPresent())
72 .collect(Collectors
.toUnmodifiableSet())
74 if (noUuidCapability
> 0) {
75 System
.err
.println("Cannot create a V2 group as " + noUuidCapability
+ " members don't have a UUID.");
79 final int noGv2Capability
= members
.stream()
80 .map(profileProvider
::getProfile
)
81 .filter(profile
-> !profile
.getCapabilities().gv2
)
82 .collect(Collectors
.toUnmodifiableSet())
84 if (noGv2Capability
> 0) {
85 System
.err
.println("Cannot create a V2 group as " + noGv2Capability
+ " members don't support Groups V2.");
89 GroupCandidate self
= new GroupCandidate(selfAddressProvider
.getSelfAddress().getUuid().orNull(),
90 Optional
.fromNullable(profileKeyCredential
));
91 Set
<GroupCandidate
> candidates
= members
.stream()
92 .map(member
-> new GroupCandidate(member
.getUuid().get(),
93 Optional
.fromNullable(profileKeyCredentialProvider
.getProfileKeyCredential(member
))))
94 .collect(Collectors
.toSet());
96 final GroupSecretParams groupSecretParams
= GroupSecretParams
.generate();
97 return groupsV2Operations
.createNewGroup(groupSecretParams
,
99 Optional
.fromNullable(avatar
),