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 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
.title
;
91 public String
getDescription() {
92 if (this.group
== null) {
95 return this.group
.description
;
99 public GroupInviteLinkUrl
getGroupInviteLink() {
100 if (this.group
== null || this.group
.inviteLinkPassword
.toByteArray().length
== 0 || (
101 this.group
.accessControl
!= null
102 && this.group
.accessControl
.addFromInviteLink
!= AccessControl
.AccessRequired
.ANY
103 && this.group
.accessControl
.addFromInviteLink
!= AccessControl
.AccessRequired
.ADMINISTRATOR
108 return GroupInviteLinkUrl
.forGroup(masterKey
, group
);
112 public Set
<RecipientId
> getMembers() {
113 if (this.group
== null) {
116 return group
.members
.stream()
117 .map(m
-> ServiceId
.parseOrThrow(m
.aciBytes
))
118 .map(recipientResolver
::resolveRecipient
)
119 .collect(Collectors
.toSet());
123 public Set
<RecipientId
> getBannedMembers() {
124 if (this.group
== null) {
127 return group
.bannedMembers
.stream()
128 .map(m
-> ServiceId
.parseOrThrow(m
.serviceIdBytes
))
129 .map(recipientResolver
::resolveRecipient
)
130 .collect(Collectors
.toSet());
134 public Set
<RecipientId
> getPendingMembers() {
135 if (this.group
== null) {
138 return group
.pendingMembers
.stream()
139 .map(m
-> ServiceId
.parseOrThrow(m
.serviceIdBytes
))
140 .map(recipientResolver
::resolveRecipient
)
141 .collect(Collectors
.toSet());
145 public Set
<RecipientId
> getRequestingMembers() {
146 if (this.group
== null) {
149 return group
.requestingMembers
.stream()
150 .map(m
-> ServiceId
.parseOrThrow(m
.aciBytes
))
151 .map(recipientResolver
::resolveRecipient
)
152 .collect(Collectors
.toSet());
156 public Set
<RecipientId
> getAdminMembers() {
157 if (this.group
== null) {
160 return group
.members
.stream()
161 .filter(m
-> m
.role
== Member
.Role
.ADMINISTRATOR
)
162 .map(m
-> new RecipientAddress(ServiceId
.ACI
.parseOrNull(m
.aciBytes
),
163 ServiceId
.PNI
.parseOrNull(m
.pniBytes
),
165 .map(recipientResolver
::resolveRecipient
)
166 .collect(Collectors
.toSet());
170 public boolean isBlocked() {
175 public void setBlocked(final boolean blocked
) {
176 this.blocked
= blocked
;
180 public int getMessageExpirationTimer() {
181 return this.group
!= null && this.group
.disappearingMessagesTimer
!= null
182 ?
this.group
.disappearingMessagesTimer
.duration
187 public boolean isAnnouncementGroup() {
188 return this.group
!= null && this.group
.isAnnouncementGroup
== EnabledState
.ENABLED
;
192 public GroupPermission
getPermissionAddMember() {
193 final var accessControl
= getAccessControl();
194 return accessControl
== null ? GroupPermission
.EVERY_MEMBER
: toGroupPermission(accessControl
.members
);
198 public GroupPermission
getPermissionEditDetails() {
199 final var accessControl
= getAccessControl();
200 return accessControl
== null ? GroupPermission
.EVERY_MEMBER
: toGroupPermission(accessControl
.attributes
);
204 public GroupPermission
getPermissionSendMessage() {
205 return isAnnouncementGroup() ? GroupPermission
.ONLY_ADMINS
: GroupPermission
.EVERY_MEMBER
;
208 public void setPermissionDenied(final boolean permissionDenied
) {
209 this.permissionDenied
= permissionDenied
;
212 public boolean isPermissionDenied() {
213 return permissionDenied
;
216 private AccessControl
getAccessControl() {
217 if (this.group
== null || this.group
.accessControl
== null) {
221 return this.group
.accessControl
;
224 private static GroupPermission
toGroupPermission(final AccessControl
.AccessRequired permission
) {
225 return switch (permission
) {
226 case ADMINISTRATOR
-> GroupPermission
.ONLY_ADMINS
;
227 default -> GroupPermission
.EVERY_MEMBER
;