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 DecryptedGroup group
;
27 private byte[] storageRecord
;
28 private boolean permissionDenied
;
30 private final RecipientResolver recipientResolver
;
33 final GroupIdV2 groupId
, final GroupMasterKey masterKey
, final RecipientResolver recipientResolver
35 this.groupId
= groupId
;
36 this.masterKey
= masterKey
;
37 this.distributionId
= DistributionId
.create();
38 this.recipientResolver
= recipientResolver
;
42 final GroupIdV2 groupId
,
43 final GroupMasterKey masterKey
,
44 final DecryptedGroup group
,
45 final DistributionId distributionId
,
46 final boolean blocked
,
47 final boolean permissionDenied
,
48 final byte[] storageRecord
,
49 final RecipientResolver recipientResolver
51 this.groupId
= groupId
;
52 this.masterKey
= masterKey
;
54 this.distributionId
= distributionId
;
55 this.blocked
= blocked
;
56 this.permissionDenied
= permissionDenied
;
57 this.storageRecord
= storageRecord
;
58 this.recipientResolver
= recipientResolver
;
62 public GroupIdV2
getGroupId() {
66 public GroupMasterKey
getMasterKey() {
70 public byte[] getStorageRecord() {
74 public DistributionId
getDistributionId() {
75 return distributionId
;
78 public void setGroup(final DecryptedGroup group
) {
80 this.permissionDenied
= false;
85 public DecryptedGroup
getGroup() {
90 public String
getTitle() {
91 if (this.group
== null) {
94 return this.group
.title
;
98 public String
getDescription() {
99 if (this.group
== null) {
102 return this.group
.description
;
106 public GroupInviteLinkUrl
getGroupInviteLink() {
107 if (this.group
== null || this.group
.inviteLinkPassword
.toByteArray().length
== 0 || (
108 this.group
.accessControl
!= null
109 && this.group
.accessControl
.addFromInviteLink
!= AccessControl
.AccessRequired
.ANY
110 && this.group
.accessControl
.addFromInviteLink
!= AccessControl
.AccessRequired
.ADMINISTRATOR
115 return GroupInviteLinkUrl
.forGroup(masterKey
, group
);
119 public Set
<RecipientId
> getMembers() {
120 if (this.group
== null) {
123 return group
.members
.stream()
124 .map(m
-> ServiceId
.parseOrThrow(m
.aciBytes
))
125 .map(recipientResolver
::resolveRecipient
)
126 .collect(Collectors
.toSet());
130 public Set
<RecipientId
> getBannedMembers() {
131 if (this.group
== null) {
134 return group
.bannedMembers
.stream()
135 .map(m
-> ServiceId
.parseOrThrow(m
.serviceIdBytes
))
136 .map(recipientResolver
::resolveRecipient
)
137 .collect(Collectors
.toSet());
141 public Set
<RecipientId
> getPendingMembers() {
142 if (this.group
== null) {
145 return group
.pendingMembers
.stream()
146 .map(m
-> ServiceId
.parseOrThrow(m
.serviceIdBytes
))
147 .map(recipientResolver
::resolveRecipient
)
148 .collect(Collectors
.toSet());
152 public Set
<RecipientId
> getRequestingMembers() {
153 if (this.group
== null) {
156 return group
.requestingMembers
.stream()
157 .map(m
-> ServiceId
.parseOrThrow(m
.aciBytes
))
158 .map(recipientResolver
::resolveRecipient
)
159 .collect(Collectors
.toSet());
163 public Set
<RecipientId
> getAdminMembers() {
164 if (this.group
== null) {
167 return group
.members
.stream()
168 .filter(m
-> m
.role
== Member
.Role
.ADMINISTRATOR
)
169 .map(m
-> new RecipientAddress(ServiceId
.ACI
.parseOrNull(m
.aciBytes
),
170 ServiceId
.PNI
.parseOrNull(m
.pniBytes
),
172 .map(recipientResolver
::resolveRecipient
)
173 .collect(Collectors
.toSet());
177 public boolean isBlocked() {
182 public void setBlocked(final boolean blocked
) {
183 this.blocked
= blocked
;
187 public int getMessageExpirationTimer() {
188 return this.group
!= null && this.group
.disappearingMessagesTimer
!= null
189 ?
this.group
.disappearingMessagesTimer
.duration
194 public boolean isAnnouncementGroup() {
195 return this.group
!= null && this.group
.isAnnouncementGroup
== EnabledState
.ENABLED
;
199 public GroupPermission
getPermissionAddMember() {
200 final var accessControl
= getAccessControl();
201 return accessControl
== null ? GroupPermission
.EVERY_MEMBER
: toGroupPermission(accessControl
.members
);
205 public GroupPermission
getPermissionEditDetails() {
206 final var accessControl
= getAccessControl();
207 return accessControl
== null ? GroupPermission
.EVERY_MEMBER
: toGroupPermission(accessControl
.attributes
);
211 public GroupPermission
getPermissionSendMessage() {
212 return isAnnouncementGroup() ? GroupPermission
.ONLY_ADMINS
: GroupPermission
.EVERY_MEMBER
;
215 public void setPermissionDenied(final boolean permissionDenied
) {
216 this.permissionDenied
= permissionDenied
;
219 public boolean isPermissionDenied() {
220 return permissionDenied
;
223 private AccessControl
getAccessControl() {
224 if (this.group
== null || this.group
.accessControl
== null) {
228 return this.group
.accessControl
;
231 private static GroupPermission
toGroupPermission(final AccessControl
.AccessRequired permission
) {
232 return switch (permission
) {
233 case ADMINISTRATOR
-> GroupPermission
.ONLY_ADMINS
;
234 default -> GroupPermission
.EVERY_MEMBER
;