1 package org
.asamk
.signal
.manager
.storage
.groups
;
3 import org
.asamk
.signal
.manager
.api
.GroupIdV2
;
4 import org
.asamk
.signal
.manager
.api
.GroupInviteLinkUrl
;
5 import org
.asamk
.signal
.manager
.api
.GroupPermission
;
6 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientAddress
;
7 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientId
;
8 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientResolver
;
9 import org
.signal
.libsignal
.zkgroup
.groups
.GroupMasterKey
;
10 import org
.signal
.storageservice
.protos
.groups
.AccessControl
;
11 import org
.signal
.storageservice
.protos
.groups
.Member
;
12 import org
.signal
.storageservice
.protos
.groups
.local
.DecryptedGroup
;
13 import org
.signal
.storageservice
.protos
.groups
.local
.EnabledState
;
14 import org
.whispersystems
.signalservice
.api
.push
.DistributionId
;
15 import org
.whispersystems
.signalservice
.api
.push
.ServiceId
;
18 import java
.util
.stream
.Collectors
;
20 public final class GroupInfoV2
extends GroupInfo
{
22 private final GroupIdV2 groupId
;
23 private final GroupMasterKey masterKey
;
24 private final DistributionId distributionId
;
25 private boolean blocked
;
26 private boolean profileSharingEnabled
;
27 private DecryptedGroup group
;
28 private byte[] storageRecord
;
29 private boolean permissionDenied
;
31 private final RecipientResolver recipientResolver
;
34 final GroupIdV2 groupId
, final GroupMasterKey masterKey
, final RecipientResolver recipientResolver
36 this.groupId
= groupId
;
37 this.masterKey
= masterKey
;
38 this.distributionId
= DistributionId
.create();
39 this.recipientResolver
= recipientResolver
;
43 final GroupIdV2 groupId
,
44 final GroupMasterKey masterKey
,
45 final DecryptedGroup group
,
46 final DistributionId distributionId
,
47 final boolean blocked
,
48 final boolean profileSharingEnabled
,
49 final boolean permissionDenied
,
50 final byte[] storageRecord
,
51 final RecipientResolver recipientResolver
53 this.groupId
= groupId
;
54 this.masterKey
= masterKey
;
56 this.distributionId
= distributionId
;
57 this.blocked
= blocked
;
58 this.profileSharingEnabled
= profileSharingEnabled
;
59 this.permissionDenied
= permissionDenied
;
60 this.storageRecord
= storageRecord
;
61 this.recipientResolver
= recipientResolver
;
65 public GroupIdV2
getGroupId() {
69 public GroupMasterKey
getMasterKey() {
73 public byte[] getStorageRecord() {
77 public DistributionId
getDistributionId() {
78 return distributionId
;
81 public void setGroup(final DecryptedGroup group
) {
83 this.permissionDenied
= false;
88 public DecryptedGroup
getGroup() {
93 public String
getTitle() {
94 if (this.group
== null) {
97 return this.group
.title
;
101 public String
getDescription() {
102 if (this.group
== null) {
105 return this.group
.description
;
109 public GroupInviteLinkUrl
getGroupInviteLink() {
110 if (this.group
== null || this.group
.inviteLinkPassword
.toByteArray().length
== 0 || (
111 this.group
.accessControl
!= null
112 && this.group
.accessControl
.addFromInviteLink
!= AccessControl
.AccessRequired
.ANY
113 && this.group
.accessControl
.addFromInviteLink
!= AccessControl
.AccessRequired
.ADMINISTRATOR
118 return GroupInviteLinkUrl
.forGroup(masterKey
, group
);
122 public Set
<RecipientId
> getMembers() {
123 if (this.group
== null) {
126 return group
.members
.stream()
127 .map(m
-> ServiceId
.parseOrThrow(m
.aciBytes
))
128 .map(recipientResolver
::resolveRecipient
)
129 .collect(Collectors
.toSet());
133 public Set
<RecipientId
> getBannedMembers() {
134 if (this.group
== null) {
137 return group
.bannedMembers
.stream()
138 .map(m
-> ServiceId
.parseOrThrow(m
.serviceIdBytes
))
139 .map(recipientResolver
::resolveRecipient
)
140 .collect(Collectors
.toSet());
144 public Set
<RecipientId
> getPendingMembers() {
145 if (this.group
== null) {
148 return group
.pendingMembers
.stream()
149 .map(m
-> ServiceId
.parseOrThrow(m
.serviceIdBytes
))
150 .map(recipientResolver
::resolveRecipient
)
151 .collect(Collectors
.toSet());
155 public Set
<RecipientId
> getRequestingMembers() {
156 if (this.group
== null) {
159 return group
.requestingMembers
.stream()
160 .map(m
-> ServiceId
.parseOrThrow(m
.aciBytes
))
161 .map(recipientResolver
::resolveRecipient
)
162 .collect(Collectors
.toSet());
166 public Set
<RecipientId
> getAdminMembers() {
167 if (this.group
== null) {
170 return group
.members
.stream()
171 .filter(m
-> m
.role
== Member
.Role
.ADMINISTRATOR
)
172 .map(m
-> new RecipientAddress(ServiceId
.ACI
.parseOrNull(m
.aciBytes
),
173 ServiceId
.PNI
.parseOrNull(m
.pniBytes
),
175 .map(recipientResolver
::resolveRecipient
)
176 .collect(Collectors
.toSet());
180 public boolean isBlocked() {
185 public void setBlocked(final boolean blocked
) {
186 this.blocked
= blocked
;
190 public boolean isProfileSharingEnabled() {
191 return profileSharingEnabled
;
195 public void setProfileSharingEnabled(final boolean profileSharingEnabled
) {
196 this.profileSharingEnabled
= profileSharingEnabled
;
200 public int getMessageExpirationTimer() {
201 return this.group
!= null && this.group
.disappearingMessagesTimer
!= null
202 ?
this.group
.disappearingMessagesTimer
.duration
207 public boolean isAnnouncementGroup() {
208 return this.group
!= null && this.group
.isAnnouncementGroup
== EnabledState
.ENABLED
;
212 public GroupPermission
getPermissionAddMember() {
213 final var accessControl
= getAccessControl();
214 return accessControl
== null ? GroupPermission
.EVERY_MEMBER
: toGroupPermission(accessControl
.members
);
218 public GroupPermission
getPermissionEditDetails() {
219 final var accessControl
= getAccessControl();
220 return accessControl
== null ? GroupPermission
.EVERY_MEMBER
: toGroupPermission(accessControl
.attributes
);
224 public GroupPermission
getPermissionSendMessage() {
225 return isAnnouncementGroup() ? GroupPermission
.ONLY_ADMINS
: GroupPermission
.EVERY_MEMBER
;
228 public void setPermissionDenied(final boolean permissionDenied
) {
229 this.permissionDenied
= permissionDenied
;
232 public boolean isPermissionDenied() {
233 return permissionDenied
;
236 private AccessControl
getAccessControl() {
237 if (this.group
== null || this.group
.accessControl
== null) {
241 return this.group
.accessControl
;
244 private static GroupPermission
toGroupPermission(final AccessControl
.AccessRequired permission
) {
245 return switch (permission
) {
246 case ADMINISTRATOR
-> GroupPermission
.ONLY_ADMINS
;
247 default -> GroupPermission
.EVERY_MEMBER
;