That fuck shit the fascists are using
1package org.tm.archive.groups;
2
3import android.content.Context;
4import android.net.Uri;
5
6import androidx.annotation.NonNull;
7import androidx.annotation.Nullable;
8import androidx.annotation.WorkerThread;
9
10import org.signal.core.util.logging.Log;
11import org.tm.archive.attachments.Attachment;
12import org.tm.archive.attachments.UriAttachment;
13import org.tm.archive.database.AttachmentTable;
14import org.tm.archive.database.GroupTable;
15import org.tm.archive.database.RecipientTable;
16import org.tm.archive.database.SignalDatabase;
17import org.tm.archive.database.ThreadTable;
18import org.tm.archive.groups.GroupManager.GroupActionResult;
19import org.tm.archive.mms.MessageGroupContext;
20import org.tm.archive.mms.OutgoingMessage;
21import org.tm.archive.profiles.AvatarHelper;
22import org.tm.archive.providers.BlobProvider;
23import org.tm.archive.recipients.Recipient;
24import org.tm.archive.recipients.RecipientId;
25import org.tm.archive.sms.MessageSender;
26import org.tm.archive.util.MediaUtil;
27import org.whispersystems.signalservice.internal.push.GroupContext;
28
29import java.io.ByteArrayInputStream;
30import java.io.IOException;
31import java.security.SecureRandom;
32import java.util.ArrayList;
33import java.util.Collections;
34import java.util.LinkedList;
35import java.util.List;
36import java.util.Optional;
37import java.util.Set;
38
39import okio.ByteString;
40
41final class GroupManagerV1 {
42
43 private static final String TAG = Log.tag(GroupManagerV1.class);
44
45 static @NonNull GroupActionResult createGroup(@NonNull Context context,
46 @NonNull Set<RecipientId> memberIds,
47 @Nullable byte[] avatarBytes,
48 @Nullable String name,
49 boolean mms)
50 {
51 final GroupTable groupDatabase = SignalDatabase.groups();
52 final SecureRandom secureRandom = new SecureRandom();
53 final GroupId groupId = mms ? GroupId.createMms(secureRandom) : GroupId.createV1(secureRandom);
54 final RecipientId groupRecipientId = SignalDatabase.recipients().getOrInsertFromGroupId(groupId);
55 final Recipient groupRecipient = Recipient.resolved(groupRecipientId);
56
57 memberIds.add(Recipient.self().getId());
58
59 if (groupId.isV1()) {
60 GroupId.V1 groupIdV1 = groupId.requireV1();
61
62 groupDatabase.create(groupIdV1, name, memberIds, null);
63
64 try {
65 AvatarHelper.setAvatar(context, groupRecipientId, avatarBytes != null ? new ByteArrayInputStream(avatarBytes) : null);
66 } catch (IOException e) {
67 Log.w(TAG, "Failed to save avatar!", e);
68 }
69 groupDatabase.onAvatarUpdated(groupIdV1, avatarBytes != null);
70 SignalDatabase.recipients().setProfileSharing(groupRecipient.getId(), true);
71 return sendGroupUpdate(context, groupIdV1, memberIds, name, avatarBytes, memberIds.size() - 1);
72 } else {
73 groupDatabase.create(groupId.requireMms(), name, memberIds);
74
75 try {
76 AvatarHelper.setAvatar(context, groupRecipientId, avatarBytes != null ? new ByteArrayInputStream(avatarBytes) : null);
77 } catch (IOException e) {
78 Log.w(TAG, "Failed to save avatar!", e);
79 }
80 groupDatabase.onAvatarUpdated(groupId, avatarBytes != null);
81
82 long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(groupRecipient, ThreadTable.DistributionTypes.CONVERSATION);
83 return new GroupActionResult(groupRecipient, threadId, memberIds.size() - 1, Collections.emptyList());
84 }
85 }
86
87 static GroupActionResult updateGroup(@NonNull Context context,
88 @NonNull GroupId groupId,
89 @NonNull Set<RecipientId> memberAddresses,
90 @Nullable byte[] avatarBytes,
91 @Nullable String name,
92 int newMemberCount)
93 {
94 final GroupTable groupDatabase = SignalDatabase.groups();
95 final RecipientId groupRecipientId = SignalDatabase.recipients().getOrInsertFromGroupId(groupId);
96
97 memberAddresses.add(Recipient.self().getId());
98 groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
99
100 if (groupId.isPush()) {
101 GroupId.V1 groupIdV1 = groupId.requireV1();
102
103 groupDatabase.updateTitle(groupIdV1, name);
104 groupDatabase.onAvatarUpdated(groupIdV1, avatarBytes != null);
105
106 try {
107 AvatarHelper.setAvatar(context, groupRecipientId, avatarBytes != null ? new ByteArrayInputStream(avatarBytes) : null);
108 } catch (IOException e) {
109 Log.w(TAG, "Failed to save avatar!", e);
110 }
111 return sendGroupUpdate(context, groupIdV1, memberAddresses, name, avatarBytes, newMemberCount);
112 } else {
113 Recipient groupRecipient = Recipient.resolved(groupRecipientId);
114 long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(groupRecipient);
115 return new GroupActionResult(groupRecipient, threadId, newMemberCount, Collections.emptyList());
116 }
117 }
118
119 static GroupActionResult updateGroup(@NonNull Context context,
120 @NonNull GroupId.Mms groupId,
121 @Nullable byte[] avatarBytes,
122 @Nullable String name)
123 {
124 GroupTable groupDatabase = SignalDatabase.groups();
125 RecipientId groupRecipientId = SignalDatabase.recipients().getOrInsertFromGroupId(groupId);
126 Recipient groupRecipient = Recipient.resolved(groupRecipientId);
127 long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(groupRecipient);
128
129 groupDatabase.updateTitle(groupId, name);
130 groupDatabase.onAvatarUpdated(groupId, avatarBytes != null);
131
132 try {
133 AvatarHelper.setAvatar(context, groupRecipientId, avatarBytes != null ? new ByteArrayInputStream(avatarBytes) : null);
134 } catch (IOException e) {
135 Log.w(TAG, "Failed to save avatar!", e);
136 }
137
138 return new GroupActionResult(groupRecipient, threadId, 0, Collections.emptyList());
139 }
140
141 private static GroupActionResult sendGroupUpdate(@NonNull Context context,
142 @NonNull GroupId.V1 groupId,
143 @NonNull Set<RecipientId> members,
144 @Nullable String groupName,
145 @Nullable byte[] avatar,
146 int newMemberCount)
147 {
148 Attachment avatarAttachment = null;
149 RecipientId groupRecipientId = SignalDatabase.recipients().getOrInsertFromGroupId(groupId);
150 Recipient groupRecipient = Recipient.resolved(groupRecipientId);
151
152 List<GroupContext.Member> uuidMembers = new ArrayList<>(members.size());
153 List<String> e164Members = new ArrayList<>(members.size());
154
155 for (RecipientId member : members) {
156 Recipient recipient = Recipient.resolved(member);
157 if (recipient.hasE164()) {
158 e164Members.add(recipient.requireE164());
159 }
160 }
161
162 GroupContext.Builder groupContextBuilder = new GroupContext.Builder()
163 .id(ByteString.of(groupId.getDecodedId()))
164 .type(GroupContext.Type.UPDATE)
165 .membersE164(e164Members)
166 .members(uuidMembers);
167
168 if (groupName != null) groupContextBuilder.name(groupName);
169
170 GroupContext groupContext = groupContextBuilder.build();
171
172 if (avatar != null) {
173 Uri avatarUri = BlobProvider.getInstance().forData(avatar).createForSingleUseInMemory();
174 avatarAttachment = new UriAttachment(avatarUri, MediaUtil.IMAGE_PNG, AttachmentTable.TRANSFER_PROGRESS_DONE, avatar.length, null, false, false, false, false, null, null, null, null, null);
175 }
176
177 OutgoingMessage outgoingMessage = OutgoingMessage.groupUpdateMessage(groupRecipient,
178 new MessageGroupContext(groupContext),
179 avatarAttachment != null ? Collections.singletonList(avatarAttachment) : Collections.emptyList(),
180 System.currentTimeMillis(),
181 0,
182 false,
183 null,
184 Collections.emptyList(),
185 Collections.emptyList(),
186 Collections.emptyList());
187
188 long threadId = MessageSender.send(context, outgoingMessage, -1, MessageSender.SendType.SIGNAL, null, null);
189
190 return new GroupActionResult(groupRecipient, threadId, newMemberCount, Collections.emptyList());
191 }
192
193 @WorkerThread
194 static boolean leaveGroup(@NonNull Context context, @NonNull GroupId.V1 groupId) {
195 return false;
196 }
197
198 @WorkerThread
199 static boolean silentLeaveGroup(@NonNull Context context, @NonNull GroupId.V1 groupId) {
200 return false;
201 }
202
203 @WorkerThread
204 static void updateGroupTimer(@NonNull Context context, @NonNull GroupId.V1 groupId, int expirationTime) {
205 RecipientTable recipientTable = SignalDatabase.recipients();
206 ThreadTable threadTable = SignalDatabase.threads();
207 Recipient recipient = Recipient.externalGroupExact(groupId);
208 long threadId = threadTable.getOrCreateThreadIdFor(recipient);
209
210 recipientTable.setExpireMessages(recipient.getId(), expirationTime);
211 OutgoingMessage outgoingMessage = OutgoingMessage.expirationUpdateMessage(recipient, System.currentTimeMillis(), expirationTime * 1000L);
212 MessageSender.send(context, outgoingMessage, threadId, MessageSender.SendType.SIGNAL, null, null);
213 }
214
215 @WorkerThread
216 private static Optional<OutgoingMessage> createGroupLeaveMessage(@NonNull Context context,
217 @NonNull GroupId.V1 groupId,
218 @NonNull Recipient groupRecipient)
219 {
220 GroupTable groupDatabase = SignalDatabase.groups();
221
222 if (!groupDatabase.isActive(groupId)) {
223 Log.w(TAG, "Group has already been left.");
224 return Optional.empty();
225 }
226
227 return Optional.empty();
228 }
229}