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 DistributionId distributionId
;
25 private boolean blocked
;
26 private DecryptedGroup group
;
27 private boolean permissionDenied
;
29 private final RecipientResolver recipientResolver
;
32 final GroupIdV2 groupId
, final GroupMasterKey masterKey
, final RecipientResolver recipientResolver
34 this.groupId
= groupId
;
35 this.masterKey
= masterKey
;
36 this.distributionId
= DistributionId
.create();
37 this.recipientResolver
= recipientResolver
;
41 final GroupIdV2 groupId
,
42 final GroupMasterKey masterKey
,
43 final DecryptedGroup group
,
44 final DistributionId distributionId
,
45 final boolean blocked
,
46 final boolean permissionDenied
,
47 final RecipientResolver recipientResolver
49 this.groupId
= groupId
;
50 this.masterKey
= masterKey
;
52 this.distributionId
= distributionId
;
53 this.blocked
= blocked
;
54 this.permissionDenied
= permissionDenied
;
55 this.recipientResolver
= recipientResolver
;
59 public GroupIdV2
getGroupId() {
63 public GroupMasterKey
getMasterKey() {
67 public DistributionId
getDistributionId() {
68 return distributionId
;
71 public void setGroup(final DecryptedGroup group
) {
73 this.permissionDenied
= false;
78 public DecryptedGroup
getGroup() {
83 public String
getTitle() {
84 if (this.group
== null) {
87 return this.group
.getTitle();
91 public String
getDescription() {
92 if (this.group
== null) {
95 return this.group
.getDescription();
99 public GroupInviteLinkUrl
getGroupInviteLink() {
100 if (this.group
== null || this.group
.getInviteLinkPassword().isEmpty() || (
101 this.group
.getAccessControl().getAddFromInviteLink() != AccessControl
.AccessRequired
.ANY
102 && this.group
.getAccessControl().getAddFromInviteLink()
103 != AccessControl
.AccessRequired
.ADMINISTRATOR
108 return GroupInviteLinkUrl
.forGroup(masterKey
, group
);
112 public Set
<RecipientId
> getMembers() {
113 if (this.group
== null) {
116 return group
.getMembersList()
118 .map(m
-> ServiceId
.parseOrThrow(m
.getAciBytes()))
119 .map(recipientResolver
::resolveRecipient
)
120 .collect(Collectors
.toSet());
124 public Set
<RecipientId
> getBannedMembers() {
125 if (this.group
== null) {
128 return group
.getBannedMembersList()
130 .map(m
-> ServiceId
.parseOrThrow(m
.getServiceIdBytes()))
131 .map(recipientResolver
::resolveRecipient
)
132 .collect(Collectors
.toSet());
136 public Set
<RecipientId
> getPendingMembers() {
137 if (this.group
== null) {
140 return group
.getPendingMembersList()
142 .map(m
-> ServiceId
.parseOrThrow(m
.getServiceIdBytes()))
143 .map(recipientResolver
::resolveRecipient
)
144 .collect(Collectors
.toSet());
148 public Set
<RecipientId
> getRequestingMembers() {
149 if (this.group
== null) {
152 return group
.getRequestingMembersList()
154 .map(m
-> ServiceId
.parseOrThrow(m
.getAciBytes()))
155 .map(recipientResolver
::resolveRecipient
)
156 .collect(Collectors
.toSet());
160 public Set
<RecipientId
> getAdminMembers() {
161 if (this.group
== null) {
164 return group
.getMembersList()
166 .filter(m
-> m
.getRole() == Member
.Role
.ADMINISTRATOR
)
167 .map(m
-> new RecipientAddress(ServiceId
.ACI
.parseOrNull(m
.getAciBytes()),
168 ServiceId
.PNI
.parseOrNull(m
.getPniBytes()),
170 .map(recipientResolver
::resolveRecipient
)
171 .collect(Collectors
.toSet());
175 public boolean isBlocked() {
180 public void setBlocked(final boolean blocked
) {
181 this.blocked
= blocked
;
185 public int getMessageExpirationTimer() {
186 return this.group
!= null && this.group
.hasDisappearingMessagesTimer()
187 ?
this.group
.getDisappearingMessagesTimer().getDuration()
192 public boolean isAnnouncementGroup() {
193 return this.group
!= null && this.group
.getIsAnnouncementGroup() == EnabledState
.ENABLED
;
197 public GroupPermission
getPermissionAddMember() {
198 final var accessControl
= getAccessControl();
199 return accessControl
== null ? GroupPermission
.EVERY_MEMBER
: toGroupPermission(accessControl
.getMembers());
203 public GroupPermission
getPermissionEditDetails() {
204 final var accessControl
= getAccessControl();
205 return accessControl
== null ? GroupPermission
.EVERY_MEMBER
: toGroupPermission(accessControl
.getAttributes());
209 public GroupPermission
getPermissionSendMessage() {
210 return isAnnouncementGroup() ? GroupPermission
.ONLY_ADMINS
: GroupPermission
.EVERY_MEMBER
;
213 public void setPermissionDenied(final boolean permissionDenied
) {
214 this.permissionDenied
= permissionDenied
;
217 public boolean isPermissionDenied() {
218 return permissionDenied
;
221 private AccessControl
getAccessControl() {
222 if (this.group
== null || !this.group
.hasAccessControl()) {
226 return this.group
.getAccessControl();
229 private static GroupPermission
toGroupPermission(final AccessControl
.AccessRequired permission
) {
230 return switch (permission
) {
231 case ADMINISTRATOR
-> GroupPermission
.ONLY_ADMINS
;
232 default -> GroupPermission
.EVERY_MEMBER
;