1 package org
.asamk
.signal
.manager
.storage
.groups
;
3 import org
.asamk
.signal
.manager
.groups
.GroupIdV2
;
4 import org
.asamk
.signal
.manager
.groups
.GroupInviteLinkUrl
;
5 import org
.asamk
.signal
.manager
.groups
.GroupPermission
;
6 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientId
;
7 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientResolver
;
8 import org
.signal
.libsignal
.zkgroup
.groups
.GroupMasterKey
;
9 import org
.signal
.storageservice
.protos
.groups
.AccessControl
;
10 import org
.signal
.storageservice
.protos
.groups
.Member
;
11 import org
.signal
.storageservice
.protos
.groups
.local
.DecryptedGroup
;
12 import org
.signal
.storageservice
.protos
.groups
.local
.EnabledState
;
13 import org
.whispersystems
.signalservice
.api
.push
.DistributionId
;
14 import org
.whispersystems
.signalservice
.api
.push
.ServiceId
;
17 import java
.util
.stream
.Collectors
;
19 public final class GroupInfoV2
extends GroupInfo
{
21 private final GroupIdV2 groupId
;
22 private final GroupMasterKey masterKey
;
23 private DistributionId distributionId
;
24 private boolean blocked
;
25 private DecryptedGroup group
; // stored as a file with base64 groupId as name
26 private boolean permissionDenied
;
28 private RecipientResolver recipientResolver
;
30 public GroupInfoV2(final GroupIdV2 groupId
, final GroupMasterKey masterKey
) {
31 this.groupId
= groupId
;
32 this.masterKey
= masterKey
;
33 this.distributionId
= DistributionId
.create();
37 final GroupIdV2 groupId
,
38 final GroupMasterKey masterKey
,
39 final DistributionId distributionId
,
40 final boolean blocked
,
41 final boolean permissionDenied
43 this.groupId
= groupId
;
44 this.masterKey
= masterKey
;
45 this.distributionId
= distributionId
;
46 this.blocked
= blocked
;
47 this.permissionDenied
= permissionDenied
;
51 public GroupIdV2
getGroupId() {
55 public GroupMasterKey
getMasterKey() {
59 public DistributionId
getDistributionId() {
60 return distributionId
;
63 public void setDistributionId(final DistributionId distributionId
) {
64 this.distributionId
= distributionId
;
67 public void setGroup(final DecryptedGroup group
, final RecipientResolver recipientResolver
) {
69 this.permissionDenied
= false;
72 this.recipientResolver
= recipientResolver
;
75 public DecryptedGroup
getGroup() {
80 public String
getTitle() {
81 if (this.group
== null) {
84 return this.group
.getTitle();
88 public String
getDescription() {
89 if (this.group
== null) {
92 return this.group
.getDescription();
96 public GroupInviteLinkUrl
getGroupInviteLink() {
97 if (this.group
== null || this.group
.getInviteLinkPassword().isEmpty() || (
98 this.group
.getAccessControl().getAddFromInviteLink() != AccessControl
.AccessRequired
.ANY
99 && this.group
.getAccessControl().getAddFromInviteLink()
100 != AccessControl
.AccessRequired
.ADMINISTRATOR
105 return GroupInviteLinkUrl
.forGroup(masterKey
, group
);
109 public Set
<RecipientId
> getMembers() {
110 if (this.group
== null) {
113 return group
.getMembersList()
115 .map(m
-> ServiceId
.fromByteString(m
.getUuid()))
116 .map(recipientResolver
::resolveRecipient
)
117 .collect(Collectors
.toSet());
121 public Set
<RecipientId
> getPendingMembers() {
122 if (this.group
== null) {
125 return group
.getPendingMembersList()
127 .map(m
-> ServiceId
.fromByteString(m
.getUuid()))
128 .map(recipientResolver
::resolveRecipient
)
129 .collect(Collectors
.toSet());
133 public Set
<RecipientId
> getRequestingMembers() {
134 if (this.group
== null) {
137 return group
.getRequestingMembersList()
139 .map(m
-> ServiceId
.fromByteString(m
.getUuid()))
140 .map(recipientResolver
::resolveRecipient
)
141 .collect(Collectors
.toSet());
145 public Set
<RecipientId
> getAdminMembers() {
146 if (this.group
== null) {
149 return group
.getMembersList()
151 .filter(m
-> m
.getRole() == Member
.Role
.ADMINISTRATOR
)
152 .map(m
-> ServiceId
.fromByteString(m
.getUuid()))
153 .map(recipientResolver
::resolveRecipient
)
154 .collect(Collectors
.toSet());
158 public boolean isBlocked() {
163 public void setBlocked(final boolean blocked
) {
164 this.blocked
= blocked
;
168 public int getMessageExpirationTimer() {
169 return this.group
!= null && this.group
.hasDisappearingMessagesTimer()
170 ?
this.group
.getDisappearingMessagesTimer().getDuration()
175 public boolean isAnnouncementGroup() {
176 return this.group
!= null && this.group
.getIsAnnouncementGroup() == EnabledState
.ENABLED
;
180 public GroupPermission
getPermissionAddMember() {
181 final var accessControl
= getAccessControl();
182 return accessControl
== null ? GroupPermission
.EVERY_MEMBER
: toGroupPermission(accessControl
.getMembers());
186 public GroupPermission
getPermissionEditDetails() {
187 final var accessControl
= getAccessControl();
188 return accessControl
== null ? GroupPermission
.EVERY_MEMBER
: toGroupPermission(accessControl
.getAttributes());
192 public GroupPermission
getPermissionSendMessage() {
193 return isAnnouncementGroup() ? GroupPermission
.ONLY_ADMINS
: GroupPermission
.EVERY_MEMBER
;
196 public void setPermissionDenied(final boolean permissionDenied
) {
197 this.permissionDenied
= permissionDenied
;
200 public boolean isPermissionDenied() {
201 return permissionDenied
;
204 private AccessControl
getAccessControl() {
205 if (this.group
== null || !this.group
.hasAccessControl()) {
209 return this.group
.getAccessControl();
212 private static GroupPermission
toGroupPermission(final AccessControl
.AccessRequired permission
) {
213 return switch (permission
) {
214 case ADMINISTRATOR
-> GroupPermission
.ONLY_ADMINS
;
215 default -> GroupPermission
.EVERY_MEMBER
;