]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupInfoV2.java
8ddec54ef308ee9b380a668bfae0ba54e6fdc8cc
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / storage / groups / GroupInfoV2.java
1 package org.asamk.signal.manager.storage.groups;
2
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;
16
17 import java.util.Set;
18 import java.util.stream.Collectors;
19
20 public final class GroupInfoV2 extends GroupInfo {
21
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;
29
30 private final RecipientResolver recipientResolver;
31
32 public GroupInfoV2(
33 final GroupIdV2 groupId, final GroupMasterKey masterKey, final RecipientResolver recipientResolver
34 ) {
35 this.groupId = groupId;
36 this.masterKey = masterKey;
37 this.distributionId = DistributionId.create();
38 this.recipientResolver = recipientResolver;
39 }
40
41 public GroupInfoV2(
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
50 ) {
51 this.groupId = groupId;
52 this.masterKey = masterKey;
53 this.group = group;
54 this.distributionId = distributionId;
55 this.blocked = blocked;
56 this.permissionDenied = permissionDenied;
57 this.storageRecord = storageRecord;
58 this.recipientResolver = recipientResolver;
59 }
60
61 @Override
62 public GroupIdV2 getGroupId() {
63 return groupId;
64 }
65
66 public GroupMasterKey getMasterKey() {
67 return masterKey;
68 }
69
70 public byte[] getStorageRecord() {
71 return storageRecord;
72 }
73
74 public DistributionId getDistributionId() {
75 return distributionId;
76 }
77
78 public void setGroup(final DecryptedGroup group) {
79 if (group != null) {
80 this.permissionDenied = false;
81 }
82 this.group = group;
83 }
84
85 public DecryptedGroup getGroup() {
86 return group;
87 }
88
89 @Override
90 public String getTitle() {
91 if (this.group == null) {
92 return null;
93 }
94 return this.group.title;
95 }
96
97 @Override
98 public String getDescription() {
99 if (this.group == null) {
100 return null;
101 }
102 return this.group.description;
103 }
104
105 @Override
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
111 )) {
112 return null;
113 }
114
115 return GroupInviteLinkUrl.forGroup(masterKey, group);
116 }
117
118 @Override
119 public Set<RecipientId> getMembers() {
120 if (this.group == null) {
121 return Set.of();
122 }
123 return group.members.stream()
124 .map(m -> ServiceId.parseOrThrow(m.aciBytes))
125 .map(recipientResolver::resolveRecipient)
126 .collect(Collectors.toSet());
127 }
128
129 @Override
130 public Set<RecipientId> getBannedMembers() {
131 if (this.group == null) {
132 return Set.of();
133 }
134 return group.bannedMembers.stream()
135 .map(m -> ServiceId.parseOrThrow(m.serviceIdBytes))
136 .map(recipientResolver::resolveRecipient)
137 .collect(Collectors.toSet());
138 }
139
140 @Override
141 public Set<RecipientId> getPendingMembers() {
142 if (this.group == null) {
143 return Set.of();
144 }
145 return group.pendingMembers.stream()
146 .map(m -> ServiceId.parseOrThrow(m.serviceIdBytes))
147 .map(recipientResolver::resolveRecipient)
148 .collect(Collectors.toSet());
149 }
150
151 @Override
152 public Set<RecipientId> getRequestingMembers() {
153 if (this.group == null) {
154 return Set.of();
155 }
156 return group.requestingMembers.stream()
157 .map(m -> ServiceId.parseOrThrow(m.aciBytes))
158 .map(recipientResolver::resolveRecipient)
159 .collect(Collectors.toSet());
160 }
161
162 @Override
163 public Set<RecipientId> getAdminMembers() {
164 if (this.group == null) {
165 return Set.of();
166 }
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),
171 null))
172 .map(recipientResolver::resolveRecipient)
173 .collect(Collectors.toSet());
174 }
175
176 @Override
177 public boolean isBlocked() {
178 return blocked;
179 }
180
181 @Override
182 public void setBlocked(final boolean blocked) {
183 this.blocked = blocked;
184 }
185
186 @Override
187 public int getMessageExpirationTimer() {
188 return this.group != null && this.group.disappearingMessagesTimer != null
189 ? this.group.disappearingMessagesTimer.duration
190 : 0;
191 }
192
193 @Override
194 public boolean isAnnouncementGroup() {
195 return this.group != null && this.group.isAnnouncementGroup == EnabledState.ENABLED;
196 }
197
198 @Override
199 public GroupPermission getPermissionAddMember() {
200 final var accessControl = getAccessControl();
201 return accessControl == null ? GroupPermission.EVERY_MEMBER : toGroupPermission(accessControl.members);
202 }
203
204 @Override
205 public GroupPermission getPermissionEditDetails() {
206 final var accessControl = getAccessControl();
207 return accessControl == null ? GroupPermission.EVERY_MEMBER : toGroupPermission(accessControl.attributes);
208 }
209
210 @Override
211 public GroupPermission getPermissionSendMessage() {
212 return isAnnouncementGroup() ? GroupPermission.ONLY_ADMINS : GroupPermission.EVERY_MEMBER;
213 }
214
215 public void setPermissionDenied(final boolean permissionDenied) {
216 this.permissionDenied = permissionDenied;
217 }
218
219 public boolean isPermissionDenied() {
220 return permissionDenied;
221 }
222
223 private AccessControl getAccessControl() {
224 if (this.group == null || this.group.accessControl == null) {
225 return null;
226 }
227
228 return this.group.accessControl;
229 }
230
231 private static GroupPermission toGroupPermission(final AccessControl.AccessRequired permission) {
232 return switch (permission) {
233 case ADMINISTRATOR -> GroupPermission.ONLY_ADMINS;
234 default -> GroupPermission.EVERY_MEMBER;
235 };
236 }
237 }