]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java
Add Pair record
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / helper / IncomingMessageHandler.java
1 package org.asamk.signal.manager.helper;
2
3 import org.asamk.signal.manager.JobExecutor;
4 import org.asamk.signal.manager.Manager;
5 import org.asamk.signal.manager.SignalDependencies;
6 import org.asamk.signal.manager.TrustLevel;
7 import org.asamk.signal.manager.UntrustedIdentityException;
8 import org.asamk.signal.manager.actions.HandleAction;
9 import org.asamk.signal.manager.actions.RefreshPreKeysAction;
10 import org.asamk.signal.manager.actions.RenewSessionAction;
11 import org.asamk.signal.manager.actions.RetrieveProfileAction;
12 import org.asamk.signal.manager.actions.RetrieveStorageDataAction;
13 import org.asamk.signal.manager.actions.SendGroupInfoAction;
14 import org.asamk.signal.manager.actions.SendGroupInfoRequestAction;
15 import org.asamk.signal.manager.actions.SendReceiptAction;
16 import org.asamk.signal.manager.actions.SendRetryMessageRequestAction;
17 import org.asamk.signal.manager.actions.SendSyncBlockedListAction;
18 import org.asamk.signal.manager.actions.SendSyncConfigurationAction;
19 import org.asamk.signal.manager.actions.SendSyncContactsAction;
20 import org.asamk.signal.manager.actions.SendSyncGroupsAction;
21 import org.asamk.signal.manager.actions.SendSyncKeysAction;
22 import org.asamk.signal.manager.api.Pair;
23 import org.asamk.signal.manager.groups.GroupId;
24 import org.asamk.signal.manager.groups.GroupNotFoundException;
25 import org.asamk.signal.manager.groups.GroupUtils;
26 import org.asamk.signal.manager.jobs.RetrieveStickerPackJob;
27 import org.asamk.signal.manager.storage.SignalAccount;
28 import org.asamk.signal.manager.storage.groups.GroupInfoV1;
29 import org.asamk.signal.manager.storage.recipients.Profile;
30 import org.asamk.signal.manager.storage.recipients.RecipientId;
31 import org.asamk.signal.manager.storage.recipients.RecipientResolver;
32 import org.asamk.signal.manager.storage.stickers.Sticker;
33 import org.asamk.signal.manager.storage.stickers.StickerPackId;
34 import org.signal.libsignal.metadata.ProtocolInvalidKeyException;
35 import org.signal.libsignal.metadata.ProtocolInvalidKeyIdException;
36 import org.signal.libsignal.metadata.ProtocolInvalidMessageException;
37 import org.signal.libsignal.metadata.ProtocolNoSessionException;
38 import org.signal.libsignal.metadata.ProtocolUntrustedIdentityException;
39 import org.signal.libsignal.metadata.SelfSendException;
40 import org.signal.zkgroup.InvalidInputException;
41 import org.signal.zkgroup.profiles.ProfileKey;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.whispersystems.libsignal.SignalProtocolAddress;
45 import org.whispersystems.signalservice.api.messages.SignalServiceContent;
46 import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
47 import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
48 import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
49 import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
50 import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOperationMessage;
51 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
52
53 import java.util.ArrayList;
54 import java.util.List;
55 import java.util.stream.Collectors;
56
57 public final class IncomingMessageHandler {
58
59 private final static Logger logger = LoggerFactory.getLogger(IncomingMessageHandler.class);
60
61 private final SignalAccount account;
62 private final SignalDependencies dependencies;
63 private final RecipientResolver recipientResolver;
64 private final SignalServiceAddressResolver addressResolver;
65 private final GroupHelper groupHelper;
66 private final ContactHelper contactHelper;
67 private final AttachmentHelper attachmentHelper;
68 private final SyncHelper syncHelper;
69 private final ProfileProvider profileProvider;
70 private final JobExecutor jobExecutor;
71
72 public IncomingMessageHandler(
73 final SignalAccount account,
74 final SignalDependencies dependencies,
75 final RecipientResolver recipientResolver,
76 final SignalServiceAddressResolver addressResolver,
77 final GroupHelper groupHelper,
78 final ContactHelper contactHelper,
79 final AttachmentHelper attachmentHelper,
80 final SyncHelper syncHelper,
81 final ProfileProvider profileProvider,
82 final JobExecutor jobExecutor
83 ) {
84 this.account = account;
85 this.dependencies = dependencies;
86 this.recipientResolver = recipientResolver;
87 this.addressResolver = addressResolver;
88 this.groupHelper = groupHelper;
89 this.contactHelper = contactHelper;
90 this.attachmentHelper = attachmentHelper;
91 this.syncHelper = syncHelper;
92 this.profileProvider = profileProvider;
93 this.jobExecutor = jobExecutor;
94 }
95
96 public Pair<List<HandleAction>, Exception> handleRetryEnvelope(
97 final SignalServiceEnvelope envelope,
98 final boolean ignoreAttachments,
99 final Manager.ReceiveMessageHandler handler
100 ) {
101 final List<HandleAction> actions = new ArrayList<>();
102 if (envelope.isPreKeySignalMessage()) {
103 actions.add(RefreshPreKeysAction.create());
104 }
105
106 SignalServiceContent content = null;
107 if (!envelope.isReceipt()) {
108 try {
109 content = dependencies.getCipher().decrypt(envelope);
110 } catch (ProtocolUntrustedIdentityException e) {
111 final var recipientId = account.getRecipientStore().resolveRecipient(e.getSender());
112 final var exception = new UntrustedIdentityException(addressResolver.resolveSignalServiceAddress(
113 recipientId), e.getSenderDevice());
114 return new Pair<>(List.of(), exception);
115 } catch (Exception e) {
116 return new Pair<>(List.of(), e);
117 }
118 }
119 actions.addAll(checkAndHandleMessage(envelope, content, ignoreAttachments, handler, null));
120 return new Pair<>(actions, null);
121 }
122
123 public Pair<List<HandleAction>, Exception> handleEnvelope(
124 final SignalServiceEnvelope envelope,
125 final boolean ignoreAttachments,
126 final Manager.ReceiveMessageHandler handler
127 ) {
128 final var actions = new ArrayList<HandleAction>();
129 if (envelope.hasSourceUuid()) {
130 // Store uuid if we don't have it already
131 // address/uuid in envelope is sent by server
132 account.getRecipientStore().resolveRecipientTrusted(envelope.getSourceAddress());
133 }
134 SignalServiceContent content = null;
135 Exception exception = null;
136 if (!envelope.isReceipt()) {
137 try {
138 content = dependencies.getCipher().decrypt(envelope);
139 } catch (ProtocolUntrustedIdentityException e) {
140 final var recipientId = account.getRecipientStore().resolveRecipient(e.getSender());
141 actions.add(new RetrieveProfileAction(recipientId));
142 exception = new UntrustedIdentityException(addressResolver.resolveSignalServiceAddress(recipientId),
143 e.getSenderDevice());
144 } catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolNoSessionException | ProtocolInvalidMessageException e) {
145 final var sender = account.getRecipientStore().resolveRecipient(e.getSender());
146 final var senderProfile = profileProvider.getProfile(sender);
147 final var selfProfile = profileProvider.getProfile(account.getSelfRecipientId());
148 if (e.getSenderDevice() != account.getDeviceId()
149 && senderProfile != null
150 && senderProfile.getCapabilities().contains(Profile.Capability.senderKey)
151 && selfProfile != null
152 && selfProfile.getCapabilities().contains(Profile.Capability.senderKey)) {
153 logger.debug("Received invalid message, requesting message resend.");
154 actions.add(new SendRetryMessageRequestAction(sender, e, envelope));
155 } else {
156 logger.debug("Received invalid message, queuing renew session action.");
157 actions.add(new RenewSessionAction(sender));
158 }
159 exception = e;
160 } catch (SelfSendException e) {
161 logger.debug("Dropping unidentified message from self.");
162 return new Pair<>(List.of(), null);
163 } catch (Exception e) {
164 exception = e;
165 }
166 }
167
168 actions.addAll(checkAndHandleMessage(envelope, content, ignoreAttachments, handler, exception));
169 return new Pair<>(actions, exception);
170 }
171
172 private List<HandleAction> checkAndHandleMessage(
173 final SignalServiceEnvelope envelope,
174 final SignalServiceContent content,
175 final boolean ignoreAttachments,
176 final Manager.ReceiveMessageHandler handler,
177 final Exception exception
178 ) {
179 if (!envelope.hasSourceUuid() && content != null) {
180 // Store uuid if we don't have it already
181 // address/uuid is validated by unidentified sender certificate
182 account.getRecipientStore().resolveRecipientTrusted(content.getSender());
183 }
184 if (isMessageBlocked(envelope, content)) {
185 logger.info("Ignoring a message from blocked user/group: {}", envelope.getTimestamp());
186 return List.of();
187 } else if (isNotAllowedToSendToGroup(envelope, content)) {
188 logger.info("Ignoring a group message from an unauthorized sender (no member or admin): {} {}",
189 (envelope.hasSourceUuid() ? envelope.getSourceAddress() : content.getSender()).getIdentifier(),
190 envelope.getTimestamp());
191 return List.of();
192 } else {
193 List<HandleAction> actions;
194 if (content != null) {
195 actions = handleMessage(envelope, content, ignoreAttachments);
196 } else {
197 actions = List.of();
198 }
199 handler.handleMessage(envelope, content, exception);
200 return actions;
201 }
202 }
203
204 public List<HandleAction> handleMessage(
205 SignalServiceEnvelope envelope, SignalServiceContent content, boolean ignoreAttachments
206 ) {
207 var actions = new ArrayList<HandleAction>();
208 final RecipientId sender;
209 final int senderDeviceId;
210 if (!envelope.isUnidentifiedSender() && envelope.hasSourceUuid()) {
211 sender = recipientResolver.resolveRecipient(envelope.getSourceAddress());
212 senderDeviceId = envelope.getSourceDevice();
213 } else {
214 sender = recipientResolver.resolveRecipient(content.getSender());
215 senderDeviceId = content.getSenderDevice();
216 }
217
218 if (content.getSenderKeyDistributionMessage().isPresent()) {
219 final var message = content.getSenderKeyDistributionMessage().get();
220 final var protocolAddress = new SignalProtocolAddress(addressResolver.resolveSignalServiceAddress(sender)
221 .getIdentifier(), senderDeviceId);
222 dependencies.getMessageSender().processSenderKeyDistributionMessage(protocolAddress, message);
223 }
224
225 if (content.getDataMessage().isPresent()) {
226 var message = content.getDataMessage().get();
227
228 if (content.isNeedsReceipt()) {
229 actions.add(new SendReceiptAction(sender, message.getTimestamp()));
230 }
231
232 actions.addAll(handleSignalServiceDataMessage(message,
233 false,
234 sender,
235 account.getSelfRecipientId(),
236 ignoreAttachments));
237 }
238
239 if (content.getSyncMessage().isPresent()) {
240 var syncMessage = content.getSyncMessage().get();
241 actions.addAll(handleSyncMessage(syncMessage, sender, ignoreAttachments));
242 }
243
244 return actions;
245 }
246
247 private List<HandleAction> handleSyncMessage(
248 final SignalServiceSyncMessage syncMessage, final RecipientId sender, final boolean ignoreAttachments
249 ) {
250 var actions = new ArrayList<HandleAction>();
251 account.setMultiDevice(true);
252 if (syncMessage.getSent().isPresent()) {
253 var message = syncMessage.getSent().get();
254 final var destination = message.getDestination().orNull();
255 actions.addAll(handleSignalServiceDataMessage(message.getMessage(),
256 true,
257 sender,
258 destination == null ? null : recipientResolver.resolveRecipient(destination),
259 ignoreAttachments));
260 }
261 if (syncMessage.getRequest().isPresent() && account.isMasterDevice()) {
262 var rm = syncMessage.getRequest().get();
263 if (rm.isContactsRequest()) {
264 actions.add(SendSyncContactsAction.create());
265 }
266 if (rm.isGroupsRequest()) {
267 actions.add(SendSyncGroupsAction.create());
268 }
269 if (rm.isBlockedListRequest()) {
270 actions.add(SendSyncBlockedListAction.create());
271 }
272 if (rm.isKeysRequest()) {
273 actions.add(SendSyncKeysAction.create());
274 }
275 if (rm.isConfigurationRequest()) {
276 actions.add(SendSyncConfigurationAction.create());
277 }
278 }
279 if (syncMessage.getGroups().isPresent()) {
280 logger.warn("Received a group v1 sync message, that can't be handled anymore, ignoring.");
281 }
282 if (syncMessage.getBlockedList().isPresent()) {
283 final var blockedListMessage = syncMessage.getBlockedList().get();
284 for (var address : blockedListMessage.getAddresses()) {
285 contactHelper.setContactBlocked(recipientResolver.resolveRecipient(address), true);
286 }
287 for (var groupId : blockedListMessage.getGroupIds()
288 .stream()
289 .map(GroupId::unknownVersion)
290 .collect(Collectors.toSet())) {
291 try {
292 groupHelper.setGroupBlocked(groupId, true);
293 } catch (GroupNotFoundException e) {
294 logger.warn("BlockedListMessage contained groupID that was not found in GroupStore: {}",
295 groupId.toBase64());
296 }
297 }
298 }
299 if (syncMessage.getContacts().isPresent()) {
300 try {
301 final var contactsMessage = syncMessage.getContacts().get();
302 attachmentHelper.retrieveAttachment(contactsMessage.getContactsStream(),
303 syncHelper::handleSyncDeviceContacts);
304 } catch (Exception e) {
305 logger.warn("Failed to handle received sync contacts, ignoring: {}", e.getMessage());
306 }
307 }
308 if (syncMessage.getVerified().isPresent()) {
309 final var verifiedMessage = syncMessage.getVerified().get();
310 account.getIdentityKeyStore()
311 .setIdentityTrustLevel(account.getRecipientStore()
312 .resolveRecipientTrusted(verifiedMessage.getDestination()),
313 verifiedMessage.getIdentityKey(),
314 TrustLevel.fromVerifiedState(verifiedMessage.getVerified()));
315 }
316 if (syncMessage.getStickerPackOperations().isPresent()) {
317 final var stickerPackOperationMessages = syncMessage.getStickerPackOperations().get();
318 for (var m : stickerPackOperationMessages) {
319 if (!m.getPackId().isPresent()) {
320 continue;
321 }
322 final var stickerPackId = StickerPackId.deserialize(m.getPackId().get());
323 final var installed = !m.getType().isPresent()
324 || m.getType().get() == StickerPackOperationMessage.Type.INSTALL;
325
326 var sticker = account.getStickerStore().getSticker(stickerPackId);
327 if (m.getPackKey().isPresent()) {
328 if (sticker == null) {
329 sticker = new Sticker(stickerPackId, m.getPackKey().get());
330 }
331 if (installed) {
332 jobExecutor.enqueueJob(new RetrieveStickerPackJob(stickerPackId, m.getPackKey().get()));
333 }
334 }
335
336 if (sticker != null) {
337 sticker.setInstalled(installed);
338 account.getStickerStore().updateSticker(sticker);
339 }
340 }
341 }
342 if (syncMessage.getFetchType().isPresent()) {
343 switch (syncMessage.getFetchType().get()) {
344 case LOCAL_PROFILE:
345 actions.add(new RetrieveProfileAction(account.getSelfRecipientId()));
346 case STORAGE_MANIFEST:
347 actions.add(RetrieveStorageDataAction.create());
348 }
349 }
350 if (syncMessage.getKeys().isPresent()) {
351 final var keysMessage = syncMessage.getKeys().get();
352 if (keysMessage.getStorageService().isPresent()) {
353 final var storageKey = keysMessage.getStorageService().get();
354 account.setStorageKey(storageKey);
355 actions.add(RetrieveStorageDataAction.create());
356 }
357 }
358 if (syncMessage.getConfiguration().isPresent()) {
359 final var configurationMessage = syncMessage.getConfiguration().get();
360 final var configurationStore = account.getConfigurationStore();
361 if (configurationMessage.getReadReceipts().isPresent()) {
362 configurationStore.setReadReceipts(configurationMessage.getReadReceipts().get());
363 }
364 if (configurationMessage.getLinkPreviews().isPresent()) {
365 configurationStore.setLinkPreviews(configurationMessage.getLinkPreviews().get());
366 }
367 if (configurationMessage.getTypingIndicators().isPresent()) {
368 configurationStore.setTypingIndicators(configurationMessage.getTypingIndicators().get());
369 }
370 if (configurationMessage.getUnidentifiedDeliveryIndicators().isPresent()) {
371 configurationStore.setUnidentifiedDeliveryIndicators(configurationMessage.getUnidentifiedDeliveryIndicators()
372 .get());
373 }
374 }
375 return actions;
376 }
377
378 private boolean isMessageBlocked(SignalServiceEnvelope envelope, SignalServiceContent content) {
379 SignalServiceAddress source;
380 if (!envelope.isUnidentifiedSender() && envelope.hasSourceUuid()) {
381 source = envelope.getSourceAddress();
382 } else if (content != null) {
383 source = content.getSender();
384 } else {
385 return false;
386 }
387 final var recipientId = recipientResolver.resolveRecipient(source);
388 if (contactHelper.isContactBlocked(recipientId)) {
389 return true;
390 }
391
392 if (content != null && content.getDataMessage().isPresent()) {
393 var message = content.getDataMessage().get();
394 if (message.getGroupContext().isPresent()) {
395 var groupId = GroupUtils.getGroupId(message.getGroupContext().get());
396 return groupHelper.isGroupBlocked(groupId);
397 }
398 }
399
400 return false;
401 }
402
403 private boolean isNotAllowedToSendToGroup(SignalServiceEnvelope envelope, SignalServiceContent content) {
404 SignalServiceAddress source;
405 if (!envelope.isUnidentifiedSender() && envelope.hasSourceUuid()) {
406 source = envelope.getSourceAddress();
407 } else if (content != null) {
408 source = content.getSender();
409 } else {
410 return false;
411 }
412
413 if (content == null || !content.getDataMessage().isPresent()) {
414 return false;
415 }
416
417 var message = content.getDataMessage().get();
418 if (!message.getGroupContext().isPresent()) {
419 return false;
420 }
421
422 if (message.getGroupContext().get().getGroupV1().isPresent()) {
423 var groupInfo = message.getGroupContext().get().getGroupV1().get();
424 if (groupInfo.getType() == SignalServiceGroup.Type.QUIT) {
425 return false;
426 }
427 }
428
429 var groupId = GroupUtils.getGroupId(message.getGroupContext().get());
430 var group = groupHelper.getGroup(groupId);
431 if (group == null) {
432 return false;
433 }
434
435 final var recipientId = recipientResolver.resolveRecipient(source);
436 if (!group.isMember(recipientId) && !(group.isPendingMember(recipientId) && message.isGroupV2Update())) {
437 return true;
438 }
439
440 if (group.isAnnouncementGroup() && !group.isAdmin(recipientId)) {
441 return message.getBody().isPresent()
442 || message.getAttachments().isPresent()
443 || message.getQuote()
444 .isPresent()
445 || message.getPreviews().isPresent()
446 || message.getMentions().isPresent()
447 || message.getSticker().isPresent();
448 }
449 return false;
450 }
451
452 private List<HandleAction> handleSignalServiceDataMessage(
453 SignalServiceDataMessage message,
454 boolean isSync,
455 RecipientId source,
456 RecipientId destination,
457 boolean ignoreAttachments
458 ) {
459 var actions = new ArrayList<HandleAction>();
460 if (message.getGroupContext().isPresent()) {
461 if (message.getGroupContext().get().getGroupV1().isPresent()) {
462 var groupInfo = message.getGroupContext().get().getGroupV1().get();
463 var groupId = GroupId.v1(groupInfo.getGroupId());
464 var group = groupHelper.getGroup(groupId);
465 if (group == null || group instanceof GroupInfoV1) {
466 var groupV1 = (GroupInfoV1) group;
467 switch (groupInfo.getType()) {
468 case UPDATE: {
469 if (groupV1 == null) {
470 groupV1 = new GroupInfoV1(groupId);
471 }
472
473 if (groupInfo.getAvatar().isPresent()) {
474 var avatar = groupInfo.getAvatar().get();
475 groupHelper.downloadGroupAvatar(groupV1.getGroupId(), avatar);
476 }
477
478 if (groupInfo.getName().isPresent()) {
479 groupV1.name = groupInfo.getName().get();
480 }
481
482 if (groupInfo.getMembers().isPresent()) {
483 groupV1.addMembers(groupInfo.getMembers()
484 .get()
485 .stream()
486 .map(recipientResolver::resolveRecipient)
487 .collect(Collectors.toSet()));
488 }
489
490 account.getGroupStore().updateGroup(groupV1);
491 break;
492 }
493 case DELIVER:
494 if (groupV1 == null && !isSync) {
495 actions.add(new SendGroupInfoRequestAction(source, groupId));
496 }
497 break;
498 case QUIT: {
499 if (groupV1 != null) {
500 groupV1.removeMember(source);
501 account.getGroupStore().updateGroup(groupV1);
502 }
503 break;
504 }
505 case REQUEST_INFO:
506 if (groupV1 != null && !isSync) {
507 actions.add(new SendGroupInfoAction(source, groupV1.getGroupId()));
508 }
509 break;
510 }
511 } else {
512 // Received a group v1 message for a v2 group
513 }
514 }
515 if (message.getGroupContext().get().getGroupV2().isPresent()) {
516 final var groupContext = message.getGroupContext().get().getGroupV2().get();
517 final var groupMasterKey = groupContext.getMasterKey();
518
519 groupHelper.getOrMigrateGroup(groupMasterKey,
520 groupContext.getRevision(),
521 groupContext.hasSignedGroupChange() ? groupContext.getSignedGroupChange() : null);
522 }
523 }
524
525 final var conversationPartnerAddress = isSync ? destination : source;
526 if (conversationPartnerAddress != null && message.isEndSession()) {
527 account.getSessionStore().deleteAllSessions(conversationPartnerAddress);
528 }
529 if (message.isExpirationUpdate() || message.getBody().isPresent()) {
530 if (message.getGroupContext().isPresent()) {
531 if (message.getGroupContext().get().getGroupV1().isPresent()) {
532 var groupInfo = message.getGroupContext().get().getGroupV1().get();
533 var group = account.getGroupStore().getOrCreateGroupV1(GroupId.v1(groupInfo.getGroupId()));
534 if (group != null) {
535 if (group.messageExpirationTime != message.getExpiresInSeconds()) {
536 group.messageExpirationTime = message.getExpiresInSeconds();
537 account.getGroupStore().updateGroup(group);
538 }
539 }
540 } else if (message.getGroupContext().get().getGroupV2().isPresent()) {
541 // disappearing message timer already stored in the DecryptedGroup
542 }
543 } else if (conversationPartnerAddress != null) {
544 contactHelper.setExpirationTimer(conversationPartnerAddress, message.getExpiresInSeconds());
545 }
546 }
547 if (!ignoreAttachments) {
548 if (message.getAttachments().isPresent()) {
549 for (var attachment : message.getAttachments().get()) {
550 attachmentHelper.downloadAttachment(attachment);
551 }
552 }
553 if (message.getSharedContacts().isPresent()) {
554 for (var contact : message.getSharedContacts().get()) {
555 if (contact.getAvatar().isPresent()) {
556 attachmentHelper.downloadAttachment(contact.getAvatar().get().getAttachment());
557 }
558 }
559 }
560 if (message.getPreviews().isPresent()) {
561 final var previews = message.getPreviews().get();
562 for (var preview : previews) {
563 if (preview.getImage().isPresent()) {
564 attachmentHelper.downloadAttachment(preview.getImage().get());
565 }
566 }
567 }
568 if (message.getQuote().isPresent()) {
569 final var quote = message.getQuote().get();
570
571 for (var quotedAttachment : quote.getAttachments()) {
572 final var thumbnail = quotedAttachment.getThumbnail();
573 if (thumbnail != null) {
574 attachmentHelper.downloadAttachment(thumbnail);
575 }
576 }
577 }
578 }
579 if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) {
580 final ProfileKey profileKey;
581 try {
582 profileKey = new ProfileKey(message.getProfileKey().get());
583 } catch (InvalidInputException e) {
584 throw new AssertionError(e);
585 }
586 if (account.getSelfRecipientId().equals(source)) {
587 this.account.setProfileKey(profileKey);
588 }
589 this.account.getProfileStore().storeProfileKey(source, profileKey);
590 }
591 if (message.getSticker().isPresent()) {
592 final var messageSticker = message.getSticker().get();
593 final var stickerPackId = StickerPackId.deserialize(messageSticker.getPackId());
594 var sticker = account.getStickerStore().getSticker(stickerPackId);
595 if (sticker == null) {
596 sticker = new Sticker(stickerPackId, messageSticker.getPackKey());
597 account.getStickerStore().updateSticker(sticker);
598 }
599 jobExecutor.enqueueJob(new RetrieveStickerPackJob(stickerPackId, messageSticker.getPackKey()));
600 }
601 return actions;
602 }
603 }