Refactor Context to create helpers lazily

This commit is contained in:
AsamK 2021-12-30 22:02:03 +01:00
parent c88c92086e
commit c7a7d00da5
41 changed files with 559 additions and 762 deletions

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager; package org.asamk.signal.manager;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
import org.asamk.signal.manager.jobs.Job; import org.asamk.signal.manager.jobs.Job;
public class JobExecutor { public class JobExecutor {

View file

@ -39,21 +39,7 @@ import org.asamk.signal.manager.groups.GroupNotFoundException;
import org.asamk.signal.manager.groups.GroupSendingNotAllowedException; import org.asamk.signal.manager.groups.GroupSendingNotAllowedException;
import org.asamk.signal.manager.groups.LastGroupAdminException; import org.asamk.signal.manager.groups.LastGroupAdminException;
import org.asamk.signal.manager.groups.NotAGroupMemberException; import org.asamk.signal.manager.groups.NotAGroupMemberException;
import org.asamk.signal.manager.helper.AttachmentHelper; import org.asamk.signal.manager.helper.Context;
import org.asamk.signal.manager.helper.ContactHelper;
import org.asamk.signal.manager.helper.GroupHelper;
import org.asamk.signal.manager.helper.GroupV2Helper;
import org.asamk.signal.manager.helper.IdentityHelper;
import org.asamk.signal.manager.helper.IncomingMessageHandler;
import org.asamk.signal.manager.helper.PinHelper;
import org.asamk.signal.manager.helper.PreKeyHelper;
import org.asamk.signal.manager.helper.ProfileHelper;
import org.asamk.signal.manager.helper.RecipientHelper;
import org.asamk.signal.manager.helper.SendHelper;
import org.asamk.signal.manager.helper.StorageHelper;
import org.asamk.signal.manager.helper.SyncHelper;
import org.asamk.signal.manager.helper.UnidentifiedAccessHelper;
import org.asamk.signal.manager.jobs.Context;
import org.asamk.signal.manager.storage.SignalAccount; import org.asamk.signal.manager.storage.SignalAccount;
import org.asamk.signal.manager.storage.groups.GroupInfo; import org.asamk.signal.manager.storage.groups.GroupInfo;
import org.asamk.signal.manager.storage.identities.IdentityInfo; import org.asamk.signal.manager.storage.identities.IdentityInfo;
@ -125,20 +111,8 @@ public class ManagerImpl implements Manager {
private final ExecutorService executor = Executors.newCachedThreadPool(); private final ExecutorService executor = Executors.newCachedThreadPool();
private final ProfileHelper profileHelper;
private final PinHelper pinHelper;
private final StorageHelper storageHelper;
private final SendHelper sendHelper;
private final SyncHelper syncHelper;
private final AttachmentHelper attachmentHelper;
private final GroupHelper groupHelper;
private final ContactHelper contactHelper;
private final IncomingMessageHandler incomingMessageHandler;
private final PreKeyHelper preKeyHelper;
private final IdentityHelper identityHelper;
private final RecipientHelper recipientHelper;
private final Context context; private final Context context;
private boolean hasCaughtUpWithOldMessages = false; private boolean hasCaughtUpWithOldMessages = false;
private boolean ignoreAttachments = false; private boolean ignoreAttachments = false;
@ -180,76 +154,7 @@ public class ManagerImpl implements Manager {
final var attachmentStore = new AttachmentStore(pathConfig.attachmentsPath()); final var attachmentStore = new AttachmentStore(pathConfig.attachmentsPath());
final var stickerPackStore = new StickerPackStore(pathConfig.stickerPacksPath()); final var stickerPackStore = new StickerPackStore(pathConfig.stickerPacksPath());
this.attachmentHelper = new AttachmentHelper(dependencies, attachmentStore); this.context = new Context(account, dependencies, avatarStore, attachmentStore, stickerPackStore);
this.pinHelper = new PinHelper(dependencies.getKeyBackupService());
final var unidentifiedAccessHelper = new UnidentifiedAccessHelper(account,
dependencies,
account::getProfileKey,
this::getRecipientProfile);
this.recipientHelper = new RecipientHelper(account, dependencies, serviceEnvironmentConfig);
this.profileHelper = new ProfileHelper(account,
dependencies,
avatarStore,
unidentifiedAccessHelper::getAccessFor,
recipientHelper::resolveSignalServiceAddress);
final GroupV2Helper groupV2Helper = new GroupV2Helper(profileHelper,
account::getSelfRecipientId,
dependencies.getGroupsV2Operations(),
dependencies.getGroupsV2Api(),
recipientHelper::resolveSignalServiceAddress);
this.sendHelper = new SendHelper(account,
dependencies,
unidentifiedAccessHelper,
recipientHelper::resolveSignalServiceAddress,
account.getRecipientStore(),
this::handleIdentityFailure,
this::getGroupInfo,
profileHelper,
recipientHelper::refreshRegisteredUser);
this.groupHelper = new GroupHelper(account,
dependencies,
attachmentHelper,
sendHelper,
groupV2Helper,
avatarStore,
recipientHelper::resolveSignalServiceAddress,
account.getRecipientStore());
this.storageHelper = new StorageHelper(account, dependencies, groupHelper, profileHelper);
this.contactHelper = new ContactHelper(account);
this.syncHelper = new SyncHelper(account,
attachmentHelper,
sendHelper,
groupHelper,
avatarStore,
recipientHelper::resolveSignalServiceAddress);
preKeyHelper = new PreKeyHelper(account, dependencies);
this.context = new Context(account,
dependencies,
stickerPackStore,
sendHelper,
groupHelper,
syncHelper,
profileHelper,
storageHelper,
preKeyHelper);
var jobExecutor = new JobExecutor(context);
this.incomingMessageHandler = new IncomingMessageHandler(account,
dependencies,
account.getRecipientStore(),
recipientHelper::resolveSignalServiceAddress,
groupHelper,
contactHelper,
attachmentHelper,
syncHelper,
profileHelper::getRecipientProfile,
jobExecutor);
this.identityHelper = new IdentityHelper(account,
dependencies,
recipientHelper::resolveSignalServiceAddress,
syncHelper,
profileHelper);
} }
@Override @Override
@ -271,7 +176,7 @@ public class ManagerImpl implements Manager {
} }
} }
try { try {
preKeyHelper.refreshPreKeysIfNecessary(); context.getPreKeyHelper().refreshPreKeysIfNecessary();
if (account.getAci() == null) { if (account.getAci() == null) {
account.setAci(ACI.parseOrNull(dependencies.getAccountManager().getWhoAmI().getAci())); account.setAci(ACI.parseOrNull(dependencies.getAccountManager().getWhoAmI().getAci()));
} }
@ -308,7 +213,7 @@ public class ManagerImpl implements Manager {
.stream() .stream()
.filter(s -> !s.isEmpty()) .filter(s -> !s.isEmpty())
.collect(Collectors.toSet()); .collect(Collectors.toSet());
final var registeredUsers = recipientHelper.getRegisteredUsers(canonicalizedNumbersSet); final var registeredUsers = context.getRecipientHelper().getRegisteredUsers(canonicalizedNumbersSet);
return numbers.stream().collect(Collectors.toMap(n -> n, n -> { return numbers.stream().collect(Collectors.toMap(n -> n, n -> {
final var number = canonicalizedNumbers.get(n); final var number = canonicalizedNumbers.get(n);
@ -370,7 +275,7 @@ public class ManagerImpl implements Manager {
if (configuration.linkPreviews().isPresent()) { if (configuration.linkPreviews().isPresent()) {
configurationStore.setLinkPreviews(configuration.linkPreviews().get()); configurationStore.setLinkPreviews(configuration.linkPreviews().get());
} }
syncHelper.sendConfigurationMessage(); context.getSyncHelper().sendConfigurationMessage();
} }
/** /**
@ -384,12 +289,13 @@ public class ManagerImpl implements Manager {
public void setProfile( public void setProfile(
String givenName, final String familyName, String about, String aboutEmoji, java.util.Optional<File> avatar String givenName, final String familyName, String about, String aboutEmoji, java.util.Optional<File> avatar
) throws IOException { ) throws IOException {
profileHelper.setProfile(givenName, context.getProfileHelper()
familyName, .setProfile(givenName,
about, familyName,
aboutEmoji, about,
avatar == null ? null : Optional.fromNullable(avatar.orElse(null))); aboutEmoji,
syncHelper.sendSyncFetchProfileMessage(); avatar == null ? null : Optional.fromNullable(avatar.orElse(null)));
context.getSyncHelper().sendSyncFetchProfileMessage();
} }
@Override @Override
@ -406,7 +312,7 @@ public class ManagerImpl implements Manager {
@Override @Override
public void deleteAccount() throws IOException { public void deleteAccount() throws IOException {
try { try {
pinHelper.removeRegistrationLockPin(); context.getPinHelper().removeRegistrationLockPin();
} catch (IOException e) { } catch (IOException e) {
logger.warn("Failed to remove registration lock pin"); logger.warn("Failed to remove registration lock pin");
} }
@ -490,28 +396,24 @@ public class ManagerImpl implements Manager {
? account.getPinMasterKey() ? account.getPinMasterKey()
: KeyUtils.createMasterKey(); : KeyUtils.createMasterKey();
pinHelper.setRegistrationLockPin(pin.get(), masterKey); context.getPinHelper().setRegistrationLockPin(pin.get(), masterKey);
account.setRegistrationLockPin(pin.get(), masterKey); account.setRegistrationLockPin(pin.get(), masterKey);
} else { } else {
// Remove KBS Pin // Remove KBS Pin
pinHelper.removeRegistrationLockPin(); context.getPinHelper().removeRegistrationLockPin();
account.setRegistrationLockPin(null, null); account.setRegistrationLockPin(null, null);
} }
} }
void refreshPreKeys() throws IOException { void refreshPreKeys() throws IOException {
preKeyHelper.refreshPreKeys(); context.getPreKeyHelper().refreshPreKeys();
} }
@Override @Override
public Profile getRecipientProfile(RecipientIdentifier.Single recipient) throws IOException, UnregisteredRecipientException { public Profile getRecipientProfile(RecipientIdentifier.Single recipient) throws IOException, UnregisteredRecipientException {
return profileHelper.getRecipientProfile(recipientHelper.resolveRecipient(recipient)); return context.getProfileHelper().getRecipientProfile(context.getRecipientHelper().resolveRecipient(recipient));
}
private Profile getRecipientProfile(RecipientId recipientId) {
return profileHelper.getRecipientProfile(recipientId);
} }
@Override @Override
@ -557,53 +459,59 @@ public class ManagerImpl implements Manager {
public SendGroupMessageResults quitGroup( public SendGroupMessageResults quitGroup(
GroupId groupId, Set<RecipientIdentifier.Single> groupAdmins GroupId groupId, Set<RecipientIdentifier.Single> groupAdmins
) throws GroupNotFoundException, IOException, NotAGroupMemberException, LastGroupAdminException, UnregisteredRecipientException { ) throws GroupNotFoundException, IOException, NotAGroupMemberException, LastGroupAdminException, UnregisteredRecipientException {
final var newAdmins = recipientHelper.resolveRecipients(groupAdmins); final var newAdmins = context.getRecipientHelper().resolveRecipients(groupAdmins);
return groupHelper.quitGroup(groupId, newAdmins); return context.getGroupHelper().quitGroup(groupId, newAdmins);
} }
@Override @Override
public void deleteGroup(GroupId groupId) throws IOException { public void deleteGroup(GroupId groupId) throws IOException {
groupHelper.deleteGroup(groupId); context.getGroupHelper().deleteGroup(groupId);
} }
@Override @Override
public Pair<GroupId, SendGroupMessageResults> createGroup( public Pair<GroupId, SendGroupMessageResults> createGroup(
String name, Set<RecipientIdentifier.Single> members, File avatarFile String name, Set<RecipientIdentifier.Single> members, File avatarFile
) throws IOException, AttachmentInvalidException, UnregisteredRecipientException { ) throws IOException, AttachmentInvalidException, UnregisteredRecipientException {
return groupHelper.createGroup(name, return context.getGroupHelper()
members == null ? null : recipientHelper.resolveRecipients(members), .createGroup(name,
avatarFile); members == null ? null : context.getRecipientHelper().resolveRecipients(members),
avatarFile);
} }
@Override @Override
public SendGroupMessageResults updateGroup( public SendGroupMessageResults updateGroup(
final GroupId groupId, final UpdateGroup updateGroup final GroupId groupId, final UpdateGroup updateGroup
) throws IOException, GroupNotFoundException, AttachmentInvalidException, NotAGroupMemberException, GroupSendingNotAllowedException, UnregisteredRecipientException { ) throws IOException, GroupNotFoundException, AttachmentInvalidException, NotAGroupMemberException, GroupSendingNotAllowedException, UnregisteredRecipientException {
return groupHelper.updateGroup(groupId, return context.getGroupHelper()
updateGroup.getName(), .updateGroup(groupId,
updateGroup.getDescription(), updateGroup.getName(),
updateGroup.getMembers() == null ? null : recipientHelper.resolveRecipients(updateGroup.getMembers()), updateGroup.getDescription(),
updateGroup.getRemoveMembers() == null updateGroup.getMembers() == null
? null ? null
: recipientHelper.resolveRecipients(updateGroup.getRemoveMembers()), : context.getRecipientHelper().resolveRecipients(updateGroup.getMembers()),
updateGroup.getAdmins() == null ? null : recipientHelper.resolveRecipients(updateGroup.getAdmins()), updateGroup.getRemoveMembers() == null
updateGroup.getRemoveAdmins() == null ? null
? null : context.getRecipientHelper().resolveRecipients(updateGroup.getRemoveMembers()),
: recipientHelper.resolveRecipients(updateGroup.getRemoveAdmins()), updateGroup.getAdmins() == null
updateGroup.isResetGroupLink(), ? null
updateGroup.getGroupLinkState(), : context.getRecipientHelper().resolveRecipients(updateGroup.getAdmins()),
updateGroup.getAddMemberPermission(), updateGroup.getRemoveAdmins() == null
updateGroup.getEditDetailsPermission(), ? null
updateGroup.getAvatarFile(), : context.getRecipientHelper().resolveRecipients(updateGroup.getRemoveAdmins()),
updateGroup.getExpirationTimer(), updateGroup.isResetGroupLink(),
updateGroup.getIsAnnouncementGroup()); updateGroup.getGroupLinkState(),
updateGroup.getAddMemberPermission(),
updateGroup.getEditDetailsPermission(),
updateGroup.getAvatarFile(),
updateGroup.getExpirationTimer(),
updateGroup.getIsAnnouncementGroup());
} }
@Override @Override
public Pair<GroupId, SendGroupMessageResults> joinGroup( public Pair<GroupId, SendGroupMessageResults> joinGroup(
GroupInviteLinkUrl inviteLinkUrl GroupInviteLinkUrl inviteLinkUrl
) throws IOException, InactiveGroupLinkException { ) throws IOException, InactiveGroupLinkException {
return groupHelper.joinGroup(inviteLinkUrl); return context.getGroupHelper().joinGroup(inviteLinkUrl);
} }
private SendMessageResults sendMessage( private SendMessageResults sendMessage(
@ -615,8 +523,8 @@ public class ManagerImpl implements Manager {
for (final var recipient : recipients) { for (final var recipient : recipients) {
if (recipient instanceof RecipientIdentifier.Single single) { if (recipient instanceof RecipientIdentifier.Single single) {
try { try {
final var recipientId = recipientHelper.resolveRecipient(single); final var recipientId = context.getRecipientHelper().resolveRecipient(single);
final var result = sendHelper.sendMessage(messageBuilder, recipientId); final var result = context.getSendHelper().sendMessage(messageBuilder, recipientId);
results.put(recipient, results.put(recipient,
List.of(SendMessageResult.from(result, List.of(SendMessageResult.from(result,
account.getRecipientStore(), account.getRecipientStore(),
@ -626,13 +534,13 @@ public class ManagerImpl implements Manager {
List.of(SendMessageResult.unregisteredFailure(single.toPartialRecipientAddress()))); List.of(SendMessageResult.unregisteredFailure(single.toPartialRecipientAddress())));
} }
} else if (recipient instanceof RecipientIdentifier.NoteToSelf) { } else if (recipient instanceof RecipientIdentifier.NoteToSelf) {
final var result = sendHelper.sendSelfMessage(messageBuilder); final var result = context.getSendHelper().sendSelfMessage(messageBuilder);
results.put(recipient, results.put(recipient,
List.of(SendMessageResult.from(result, List.of(SendMessageResult.from(result,
account.getRecipientStore(), account.getRecipientStore(),
account.getRecipientStore()::resolveRecipientAddress))); account.getRecipientStore()::resolveRecipientAddress)));
} else if (recipient instanceof RecipientIdentifier.Group group) { } else if (recipient instanceof RecipientIdentifier.Group group) {
final var result = sendHelper.sendAsGroupMessage(messageBuilder, group.groupId()); final var result = context.getSendHelper().sendAsGroupMessage(messageBuilder, group.groupId());
results.put(recipient, results.put(recipient,
result.stream() result.stream()
.map(sendMessageResult -> SendMessageResult.from(sendMessageResult, .map(sendMessageResult -> SendMessageResult.from(sendMessageResult,
@ -653,8 +561,8 @@ public class ManagerImpl implements Manager {
if (recipient instanceof RecipientIdentifier.Single single) { if (recipient instanceof RecipientIdentifier.Single single) {
final var message = new SignalServiceTypingMessage(action, timestamp, Optional.absent()); final var message = new SignalServiceTypingMessage(action, timestamp, Optional.absent());
try { try {
final var recipientId = recipientHelper.resolveRecipient(single); final var recipientId = context.getRecipientHelper().resolveRecipient(single);
final var result = sendHelper.sendTypingMessage(message, recipientId); final var result = context.getSendHelper().sendTypingMessage(message, recipientId);
results.put(recipient, results.put(recipient,
List.of(SendMessageResult.from(result, List.of(SendMessageResult.from(result,
account.getRecipientStore(), account.getRecipientStore(),
@ -666,7 +574,7 @@ public class ManagerImpl implements Manager {
} else if (recipient instanceof RecipientIdentifier.Group) { } else if (recipient instanceof RecipientIdentifier.Group) {
final var groupId = ((RecipientIdentifier.Group) recipient).groupId(); final var groupId = ((RecipientIdentifier.Group) recipient).groupId();
final var message = new SignalServiceTypingMessage(action, timestamp, Optional.of(groupId.serialize())); final var message = new SignalServiceTypingMessage(action, timestamp, Optional.of(groupId.serialize()));
final var result = sendHelper.sendGroupTypingMessage(message, groupId); final var result = context.getSendHelper().sendGroupTypingMessage(message, groupId);
results.put(recipient, results.put(recipient,
result.stream() result.stream()
.map(r -> SendMessageResult.from(r, .map(r -> SendMessageResult.from(r,
@ -715,7 +623,8 @@ public class ManagerImpl implements Manager {
final SignalServiceReceiptMessage receiptMessage final SignalServiceReceiptMessage receiptMessage
) throws IOException { ) throws IOException {
try { try {
final var result = sendHelper.sendReceiptMessage(receiptMessage, recipientHelper.resolveRecipient(sender)); final var result = context.getSendHelper()
.sendReceiptMessage(receiptMessage, context.getRecipientHelper().resolveRecipient(sender));
return new SendMessageResults(timestamp, return new SendMessageResults(timestamp,
Map.of(sender, Map.of(sender,
List.of(SendMessageResult.from(result, List.of(SendMessageResult.from(result,
@ -742,7 +651,7 @@ public class ManagerImpl implements Manager {
messageBuilder.withBody(message.messageText()); messageBuilder.withBody(message.messageText());
final var attachments = message.attachments(); final var attachments = message.attachments();
if (attachments != null) { if (attachments != null) {
messageBuilder.withAttachments(attachmentHelper.uploadAttachments(attachments)); messageBuilder.withAttachments(context.getAttachmentHelper().uploadAttachments(attachments));
} }
if (message.mentions().size() > 0) { if (message.mentions().size() > 0) {
messageBuilder.withMentions(resolveMentions(message.mentions())); messageBuilder.withMentions(resolveMentions(message.mentions()));
@ -750,7 +659,8 @@ public class ManagerImpl implements Manager {
if (message.quote().isPresent()) { if (message.quote().isPresent()) {
final var quote = message.quote().get(); final var quote = message.quote().get();
messageBuilder.withQuote(new SignalServiceDataMessage.Quote(quote.timestamp(), messageBuilder.withQuote(new SignalServiceDataMessage.Quote(quote.timestamp(),
recipientHelper.resolveSignalServiceAddress(recipientHelper.resolveRecipient(quote.author())), context.getRecipientHelper()
.resolveSignalServiceAddress(context.getRecipientHelper().resolveRecipient(quote.author())),
quote.message(), quote.message(),
List.of(), List.of(),
resolveMentions(quote.mentions()))); resolveMentions(quote.mentions())));
@ -760,8 +670,9 @@ public class ManagerImpl implements Manager {
private ArrayList<SignalServiceDataMessage.Mention> resolveMentions(final List<Message.Mention> mentionList) throws IOException, UnregisteredRecipientException { private ArrayList<SignalServiceDataMessage.Mention> resolveMentions(final List<Message.Mention> mentionList) throws IOException, UnregisteredRecipientException {
final var mentions = new ArrayList<SignalServiceDataMessage.Mention>(); final var mentions = new ArrayList<SignalServiceDataMessage.Mention>();
for (final var m : mentionList) { for (final var m : mentionList) {
final var recipientId = recipientHelper.resolveRecipient(m.recipient()); final var recipientId = context.getRecipientHelper().resolveRecipient(m.recipient());
mentions.add(new SignalServiceDataMessage.Mention(recipientHelper.resolveSignalServiceAddress(recipientId) mentions.add(new SignalServiceDataMessage.Mention(context.getRecipientHelper()
.resolveSignalServiceAddress(recipientId)
.getAci(), m.start(), m.length())); .getAci(), m.start(), m.length()));
} }
return mentions; return mentions;
@ -784,10 +695,10 @@ public class ManagerImpl implements Manager {
long targetSentTimestamp, long targetSentTimestamp,
Set<RecipientIdentifier> recipients Set<RecipientIdentifier> recipients
) throws IOException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException, UnregisteredRecipientException { ) throws IOException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException, UnregisteredRecipientException {
var targetAuthorRecipientId = recipientHelper.resolveRecipient(targetAuthor); var targetAuthorRecipientId = context.getRecipientHelper().resolveRecipient(targetAuthor);
var reaction = new SignalServiceDataMessage.Reaction(emoji, var reaction = new SignalServiceDataMessage.Reaction(emoji,
remove, remove,
recipientHelper.resolveSignalServiceAddress(targetAuthorRecipientId), context.getRecipientHelper().resolveSignalServiceAddress(targetAuthorRecipientId),
targetSentTimestamp); targetSentTimestamp);
final var messageBuilder = SignalServiceDataMessage.newBuilder().withReaction(reaction); final var messageBuilder = SignalServiceDataMessage.newBuilder().withReaction(reaction);
return sendMessage(messageBuilder, recipients); return sendMessage(messageBuilder, recipients);
@ -806,7 +717,7 @@ public class ManagerImpl implements Manager {
for (var recipient : recipients) { for (var recipient : recipients) {
final RecipientId recipientId; final RecipientId recipientId;
try { try {
recipientId = recipientHelper.resolveRecipient(recipient); recipientId = context.getRecipientHelper().resolveRecipient(recipient);
} catch (UnregisteredRecipientException e) { } catch (UnregisteredRecipientException e) {
continue; continue;
} }
@ -833,7 +744,7 @@ public class ManagerImpl implements Manager {
if (!account.isMasterDevice()) { if (!account.isMasterDevice()) {
throw new NotMasterDeviceException(); throw new NotMasterDeviceException();
} }
contactHelper.setContactName(recipientHelper.resolveRecipient(recipient), name); context.getContactHelper().setContactName(context.getRecipientHelper().resolveRecipient(recipient), name);
} }
@Override @Override
@ -843,9 +754,9 @@ public class ManagerImpl implements Manager {
if (!account.isMasterDevice()) { if (!account.isMasterDevice()) {
throw new NotMasterDeviceException(); throw new NotMasterDeviceException();
} }
contactHelper.setContactBlocked(recipientHelper.resolveRecipient(recipient), blocked); context.getContactHelper().setContactBlocked(context.getRecipientHelper().resolveRecipient(recipient), blocked);
// TODO cycle our profile key, if we're not together in a group with recipient // TODO cycle our profile key, if we're not together in a group with recipient
syncHelper.sendBlockedList(); context.getSyncHelper().sendBlockedList();
} }
@Override @Override
@ -855,9 +766,9 @@ public class ManagerImpl implements Manager {
if (!account.isMasterDevice()) { if (!account.isMasterDevice()) {
throw new NotMasterDeviceException(); throw new NotMasterDeviceException();
} }
groupHelper.setGroupBlocked(groupId, blocked); context.getGroupHelper().setGroupBlocked(groupId, blocked);
// TODO cycle our profile key // TODO cycle our profile key
syncHelper.sendBlockedList(); context.getSyncHelper().sendBlockedList();
} }
/** /**
@ -867,8 +778,8 @@ public class ManagerImpl implements Manager {
public void setExpirationTimer( public void setExpirationTimer(
RecipientIdentifier.Single recipient, int messageExpirationTimer RecipientIdentifier.Single recipient, int messageExpirationTimer
) throws IOException, UnregisteredRecipientException { ) throws IOException, UnregisteredRecipientException {
var recipientId = recipientHelper.resolveRecipient(recipient); var recipientId = context.getRecipientHelper().resolveRecipient(recipient);
contactHelper.setExpirationTimer(recipientId, messageExpirationTimer); context.getContactHelper().setExpirationTimer(recipientId, messageExpirationTimer);
final var messageBuilder = SignalServiceDataMessage.newBuilder().asExpirationUpdate(); final var messageBuilder = SignalServiceDataMessage.newBuilder().asExpirationUpdate();
try { try {
sendMessage(messageBuilder, Set.of(recipient)); sendMessage(messageBuilder, Set.of(recipient));
@ -911,13 +822,13 @@ public class ManagerImpl implements Manager {
@Override @Override
public void requestAllSyncData() throws IOException { public void requestAllSyncData() throws IOException {
syncHelper.requestAllSyncData(); context.getSyncHelper().requestAllSyncData();
retrieveRemoteStorage(); retrieveRemoteStorage();
} }
void retrieveRemoteStorage() throws IOException { void retrieveRemoteStorage() throws IOException {
if (account.getStorageKey() != null) { if (account.getStorageKey() != null) {
storageHelper.readDataFromStorage(); context.getStorageHelper().readDataFromStorage();
} }
} }
@ -941,7 +852,8 @@ public class ManagerImpl implements Manager {
return null; return null;
} }
final var result = incomingMessageHandler.handleRetryEnvelope(envelope, ignoreAttachments, handler); final var result = context.getIncomingMessageHandler()
.handleRetryEnvelope(envelope, ignoreAttachments, handler);
final var actions = result.first(); final var actions = result.first();
final var exception = result.second(); final var exception = result.second();
@ -1171,7 +1083,7 @@ public class ManagerImpl implements Manager {
continue; continue;
} }
final var result = incomingMessageHandler.handleEnvelope(envelope, ignoreAttachments, handler); final var result = context.getIncomingMessageHandler().handleEnvelope(envelope, ignoreAttachments, handler);
for (final var h : result.first()) { for (final var h : result.first()) {
final var existingAction = queuedActions.get(h); final var existingAction = queuedActions.get(h);
if (existingAction == null) { if (existingAction == null) {
@ -1256,16 +1168,16 @@ public class ManagerImpl implements Manager {
public boolean isContactBlocked(final RecipientIdentifier.Single recipient) { public boolean isContactBlocked(final RecipientIdentifier.Single recipient) {
final RecipientId recipientId; final RecipientId recipientId;
try { try {
recipientId = recipientHelper.resolveRecipient(recipient); recipientId = context.getRecipientHelper().resolveRecipient(recipient);
} catch (IOException | UnregisteredRecipientException e) { } catch (IOException | UnregisteredRecipientException e) {
return false; return false;
} }
return contactHelper.isContactBlocked(recipientId); return context.getContactHelper().isContactBlocked(recipientId);
} }
@Override @Override
public void sendContacts() throws IOException { public void sendContacts() throws IOException {
syncHelper.sendContacts(); context.getSyncHelper().sendContacts();
} }
@Override @Override
@ -1281,7 +1193,7 @@ public class ManagerImpl implements Manager {
public String getContactOrProfileName(RecipientIdentifier.Single recipient) { public String getContactOrProfileName(RecipientIdentifier.Single recipient) {
final RecipientId recipientId; final RecipientId recipientId;
try { try {
recipientId = recipientHelper.resolveRecipient(recipient); recipientId = context.getRecipientHelper().resolveRecipient(recipient);
} catch (IOException | UnregisteredRecipientException e) { } catch (IOException | UnregisteredRecipientException e) {
return null; return null;
} }
@ -1291,7 +1203,7 @@ public class ManagerImpl implements Manager {
return contact.getName(); return contact.getName();
} }
final var profile = profileHelper.getRecipientProfile(recipientId); final var profile = context.getProfileHelper().getRecipientProfile(recipientId);
if (profile != null) { if (profile != null) {
return profile.getDisplayName(); return profile.getDisplayName();
} }
@ -1301,11 +1213,7 @@ public class ManagerImpl implements Manager {
@Override @Override
public Group getGroup(GroupId groupId) { public Group getGroup(GroupId groupId) {
return toGroup(groupHelper.getGroup(groupId)); return toGroup(context.getGroupHelper().getGroup(groupId));
}
private GroupInfo getGroupInfo(GroupId groupId) {
return groupHelper.getGroup(groupId);
} }
@Override @Override
@ -1319,11 +1227,12 @@ public class ManagerImpl implements Manager {
} }
final var address = account.getRecipientStore().resolveRecipientAddress(identityInfo.getRecipientId()); final var address = account.getRecipientStore().resolveRecipientAddress(identityInfo.getRecipientId());
final var scannableFingerprint = identityHelper.computeSafetyNumberForScanning(identityInfo.getRecipientId(), final var scannableFingerprint = context.getIdentityHelper()
identityInfo.getIdentityKey()); .computeSafetyNumberForScanning(identityInfo.getRecipientId(), identityInfo.getIdentityKey());
return new Identity(address, return new Identity(address,
identityInfo.getIdentityKey(), identityInfo.getIdentityKey(),
identityHelper.computeSafetyNumber(identityInfo.getRecipientId(), identityInfo.getIdentityKey()), context.getIdentityHelper()
.computeSafetyNumber(identityInfo.getRecipientId(), identityInfo.getIdentityKey()),
scannableFingerprint == null ? null : scannableFingerprint.getSerialized(), scannableFingerprint == null ? null : scannableFingerprint.getSerialized(),
identityInfo.getTrustLevel(), identityInfo.getTrustLevel(),
identityInfo.getDateAdded()); identityInfo.getDateAdded());
@ -1333,7 +1242,8 @@ public class ManagerImpl implements Manager {
public List<Identity> getIdentities(RecipientIdentifier.Single recipient) { public List<Identity> getIdentities(RecipientIdentifier.Single recipient) {
IdentityInfo identity; IdentityInfo identity;
try { try {
identity = account.getIdentityKeyStore().getIdentity(recipientHelper.resolveRecipient(recipient)); identity = account.getIdentityKeyStore()
.getIdentity(context.getRecipientHelper().resolveRecipient(recipient));
} catch (IOException | UnregisteredRecipientException e) { } catch (IOException | UnregisteredRecipientException e) {
identity = null; identity = null;
} }
@ -1352,11 +1262,11 @@ public class ManagerImpl implements Manager {
) throws UnregisteredRecipientException { ) throws UnregisteredRecipientException {
RecipientId recipientId; RecipientId recipientId;
try { try {
recipientId = recipientHelper.resolveRecipient(recipient); recipientId = context.getRecipientHelper().resolveRecipient(recipient);
} catch (IOException e) { } catch (IOException e) {
return false; return false;
} }
final var updated = identityHelper.trustIdentityVerified(recipientId, fingerprint); final var updated = context.getIdentityHelper().trustIdentityVerified(recipientId, fingerprint);
if (updated && this.isReceiving()) { if (updated && this.isReceiving()) {
needsToRetryFailedMessages = true; needsToRetryFailedMessages = true;
} }
@ -1375,11 +1285,11 @@ public class ManagerImpl implements Manager {
) throws UnregisteredRecipientException { ) throws UnregisteredRecipientException {
RecipientId recipientId; RecipientId recipientId;
try { try {
recipientId = recipientHelper.resolveRecipient(recipient); recipientId = context.getRecipientHelper().resolveRecipient(recipient);
} catch (IOException e) { } catch (IOException e) {
return false; return false;
} }
final var updated = identityHelper.trustIdentityVerifiedSafetyNumber(recipientId, safetyNumber); final var updated = context.getIdentityHelper().trustIdentityVerifiedSafetyNumber(recipientId, safetyNumber);
if (updated && this.isReceiving()) { if (updated && this.isReceiving()) {
needsToRetryFailedMessages = true; needsToRetryFailedMessages = true;
} }
@ -1398,11 +1308,11 @@ public class ManagerImpl implements Manager {
) throws UnregisteredRecipientException { ) throws UnregisteredRecipientException {
RecipientId recipientId; RecipientId recipientId;
try { try {
recipientId = recipientHelper.resolveRecipient(recipient); recipientId = context.getRecipientHelper().resolveRecipient(recipient);
} catch (IOException e) { } catch (IOException e) {
return false; return false;
} }
final var updated = identityHelper.trustIdentityVerifiedSafetyNumber(recipientId, safetyNumber); final var updated = context.getIdentityHelper().trustIdentityVerifiedSafetyNumber(recipientId, safetyNumber);
if (updated && this.isReceiving()) { if (updated && this.isReceiving()) {
needsToRetryFailedMessages = true; needsToRetryFailedMessages = true;
} }
@ -1418,11 +1328,11 @@ public class ManagerImpl implements Manager {
public boolean trustIdentityAllKeys(RecipientIdentifier.Single recipient) throws UnregisteredRecipientException { public boolean trustIdentityAllKeys(RecipientIdentifier.Single recipient) throws UnregisteredRecipientException {
RecipientId recipientId; RecipientId recipientId;
try { try {
recipientId = recipientHelper.resolveRecipient(recipient); recipientId = context.getRecipientHelper().resolveRecipient(recipient);
} catch (IOException e) { } catch (IOException e) {
return false; return false;
} }
final var updated = identityHelper.trustIdentityAllKeys(recipientId); final var updated = context.getIdentityHelper().trustIdentityAllKeys(recipientId);
if (updated && this.isReceiving()) { if (updated && this.isReceiving()) {
needsToRetryFailedMessages = true; needsToRetryFailedMessages = true;
} }
@ -1436,13 +1346,6 @@ public class ManagerImpl implements Manager {
} }
} }
private void handleIdentityFailure(
final RecipientId recipientId,
final org.whispersystems.signalservice.api.messages.SendMessageResult.IdentityFailure identityFailure
) {
this.identityHelper.handleIdentityFailure(recipientId, identityFailure);
}
@Override @Override
public void close() throws IOException { public void close() throws IOException {
Thread thread; Thread thread;

View file

@ -68,6 +68,10 @@ public class SignalDependencies {
this.sessionLock = sessionLock; this.sessionLock = sessionLock;
} }
public ServiceEnvironmentConfig getServiceEnvironmentConfig() {
return serviceEnvironmentConfig;
}
public SignalServiceAccountManager getAccountManager() { public SignalServiceAccountManager getAccountManager() {
return getOrCreate(() -> accountManager, return getOrCreate(() -> accountManager,
() -> accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(), () -> accountManager = new SignalServiceAccountManager(serviceEnvironmentConfig.getSignalServiceConfiguration(),

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
public interface HandleAction { public interface HandleAction {

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
public class RefreshPreKeysAction implements HandleAction { public class RefreshPreKeysAction implements HandleAction {

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
public class RenewSessionAction implements HandleAction { public class RenewSessionAction implements HandleAction {

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
public class RetrieveProfileAction implements HandleAction { public class RetrieveProfileAction implements HandleAction {

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
public class RetrieveStorageDataAction implements HandleAction { public class RetrieveStorageDataAction implements HandleAction {

View file

@ -1,7 +1,7 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.groups.GroupIdV1; import org.asamk.signal.manager.groups.GroupIdV1;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
public class SendGroupInfoAction implements HandleAction { public class SendGroupInfoAction implements HandleAction {

View file

@ -1,7 +1,7 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.groups.GroupIdV1; import org.asamk.signal.manager.groups.GroupIdV1;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
public class SendGroupInfoRequestAction implements HandleAction { public class SendGroupInfoRequestAction implements HandleAction {

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
import java.util.ArrayList; import java.util.ArrayList;

View file

@ -1,7 +1,7 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupId;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
import org.signal.libsignal.metadata.ProtocolException; import org.signal.libsignal.metadata.ProtocolException;
import org.whispersystems.libsignal.protocol.CiphertextMessage; import org.whispersystems.libsignal.protocol.CiphertextMessage;

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
public class SendSyncBlockedListAction implements HandleAction { public class SendSyncBlockedListAction implements HandleAction {

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
public class SendSyncConfigurationAction implements HandleAction { public class SendSyncConfigurationAction implements HandleAction {

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
public class SendSyncContactsAction implements HandleAction { public class SendSyncContactsAction implements HandleAction {

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
public class SendSyncGroupsAction implements HandleAction { public class SendSyncGroupsAction implements HandleAction {

View file

@ -1,6 +1,6 @@
package org.asamk.signal.manager.actions; package org.asamk.signal.manager.actions;
import org.asamk.signal.manager.jobs.Context; import org.asamk.signal.manager.helper.Context;
public class SendSyncKeysAction implements HandleAction { public class SendSyncKeysAction implements HandleAction {

View file

@ -29,11 +29,9 @@ public class AttachmentHelper {
private final SignalDependencies dependencies; private final SignalDependencies dependencies;
private final AttachmentStore attachmentStore; private final AttachmentStore attachmentStore;
public AttachmentHelper( public AttachmentHelper(final Context context) {
final SignalDependencies dependencies, final AttachmentStore attachmentStore this.dependencies = context.getDependencies();
) { this.attachmentStore = context.getAttachmentStore();
this.dependencies = dependencies;
this.attachmentStore = attachmentStore;
} }
public File getAttachmentFile(SignalServiceAttachmentRemoteId attachmentId) { public File getAttachmentFile(SignalServiceAttachmentRemoteId attachmentId) {

View file

@ -0,0 +1,155 @@
package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.AttachmentStore;
import org.asamk.signal.manager.AvatarStore;
import org.asamk.signal.manager.JobExecutor;
import org.asamk.signal.manager.SignalDependencies;
import org.asamk.signal.manager.StickerPackStore;
import org.asamk.signal.manager.storage.SignalAccount;
import java.util.function.Supplier;
public class Context {
private final Object LOCK = new Object();
private final SignalAccount account;
private final SignalDependencies dependencies;
private final AvatarStore avatarStore;
private final StickerPackStore stickerPackStore;
private final AttachmentStore attachmentStore;
private final JobExecutor jobExecutor;
private AttachmentHelper attachmentHelper;
private ContactHelper contactHelper;
private GroupHelper groupHelper;
private GroupV2Helper groupV2Helper;
private IdentityHelper identityHelper;
private IncomingMessageHandler incomingMessageHandler;
private PinHelper pinHelper;
private PreKeyHelper preKeyHelper;
private ProfileHelper profileHelper;
private RecipientHelper recipientHelper;
private SendHelper sendHelper;
private StorageHelper storageHelper;
private SyncHelper syncHelper;
private UnidentifiedAccessHelper unidentifiedAccessHelper;
public Context(
final SignalAccount account,
final SignalDependencies dependencies,
final AvatarStore avatarStore,
final AttachmentStore attachmentStore,
final StickerPackStore stickerPackStore
) {
this.account = account;
this.dependencies = dependencies;
this.avatarStore = avatarStore;
this.stickerPackStore = stickerPackStore;
this.attachmentStore = attachmentStore;
this.jobExecutor = new JobExecutor(this);
}
public SignalAccount getAccount() {
return account;
}
public SignalDependencies getDependencies() {
return dependencies;
}
public AvatarStore getAvatarStore() {
return avatarStore;
}
public StickerPackStore getStickerPackStore() {
return stickerPackStore;
}
AttachmentStore getAttachmentStore() {
return attachmentStore;
}
JobExecutor getJobExecutor() {
return jobExecutor;
}
public AttachmentHelper getAttachmentHelper() {
return getOrCreate(() -> attachmentHelper, () -> attachmentHelper = new AttachmentHelper(this));
}
public ContactHelper getContactHelper() {
return getOrCreate(() -> contactHelper, () -> contactHelper = new ContactHelper(account));
}
GroupV2Helper getGroupV2Helper() {
return getOrCreate(() -> groupV2Helper, () -> groupV2Helper = new GroupV2Helper(this));
}
public GroupHelper getGroupHelper() {
return getOrCreate(() -> groupHelper, () -> groupHelper = new GroupHelper(this));
}
public IdentityHelper getIdentityHelper() {
return getOrCreate(() -> identityHelper, () -> identityHelper = new IdentityHelper(this));
}
public IncomingMessageHandler getIncomingMessageHandler() {
return getOrCreate(() -> incomingMessageHandler,
() -> this.incomingMessageHandler = new IncomingMessageHandler(this));
}
public PinHelper getPinHelper() {
return getOrCreate(() -> pinHelper, () -> pinHelper = new PinHelper(dependencies.getKeyBackupService()));
}
public PreKeyHelper getPreKeyHelper() {
return getOrCreate(() -> preKeyHelper, () -> preKeyHelper = new PreKeyHelper(account, dependencies));
}
public ProfileHelper getProfileHelper() {
return getOrCreate(() -> profileHelper, () -> profileHelper = new ProfileHelper(this));
}
public RecipientHelper getRecipientHelper() {
return getOrCreate(() -> recipientHelper, () -> recipientHelper = new RecipientHelper(this));
}
public SendHelper getSendHelper() {
return getOrCreate(() -> sendHelper, () -> sendHelper = new SendHelper(this));
}
public StorageHelper getStorageHelper() {
return getOrCreate(() -> storageHelper, () -> storageHelper = new StorageHelper(this));
}
public SyncHelper getSyncHelper() {
return getOrCreate(() -> syncHelper, () -> syncHelper = new SyncHelper(this));
}
UnidentifiedAccessHelper getUnidentifiedAccessHelper() {
return getOrCreate(() -> unidentifiedAccessHelper,
() -> unidentifiedAccessHelper = new UnidentifiedAccessHelper(this));
}
private <T> T getOrCreate(Supplier<T> supplier, Callable creator) {
var value = supplier.get();
if (value != null) {
return value;
}
synchronized (LOCK) {
value = supplier.get();
if (value != null) {
return value;
}
creator.call();
return supplier.get();
}
}
private interface Callable {
void call();
}
}

View file

@ -1,7 +1,6 @@
package org.asamk.signal.manager.helper; package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.AttachmentInvalidException; import org.asamk.signal.manager.AttachmentInvalidException;
import org.asamk.signal.manager.AvatarStore;
import org.asamk.signal.manager.SignalDependencies; import org.asamk.signal.manager.SignalDependencies;
import org.asamk.signal.manager.api.InactiveGroupLinkException; import org.asamk.signal.manager.api.InactiveGroupLinkException;
import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.Pair;
@ -24,7 +23,6 @@ import org.asamk.signal.manager.storage.groups.GroupInfo;
import org.asamk.signal.manager.storage.groups.GroupInfoV1; import org.asamk.signal.manager.storage.groups.GroupInfoV1;
import org.asamk.signal.manager.storage.groups.GroupInfoV2; import org.asamk.signal.manager.storage.groups.GroupInfoV2;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
import org.asamk.signal.manager.util.AttachmentUtils; import org.asamk.signal.manager.util.AttachmentUtils;
import org.asamk.signal.manager.util.IOUtils; import org.asamk.signal.manager.util.IOUtils;
import org.signal.storageservice.protos.groups.GroupChange; import org.signal.storageservice.protos.groups.GroupChange;
@ -63,31 +61,12 @@ public class GroupHelper {
private final SignalAccount account; private final SignalAccount account;
private final SignalDependencies dependencies; private final SignalDependencies dependencies;
private final AttachmentHelper attachmentHelper; private final Context context;
private final SendHelper sendHelper;
private final GroupV2Helper groupV2Helper;
private final AvatarStore avatarStore;
private final SignalServiceAddressResolver addressResolver;
private final RecipientResolver recipientResolver;
public GroupHelper( public GroupHelper(final Context context) {
final SignalAccount account, this.account = context.getAccount();
final SignalDependencies dependencies, this.dependencies = context.getDependencies();
final AttachmentHelper attachmentHelper, this.context = context;
final SendHelper sendHelper,
final GroupV2Helper groupV2Helper,
final AvatarStore avatarStore,
final SignalServiceAddressResolver addressResolver,
final RecipientResolver recipientResolver
) {
this.account = account;
this.dependencies = dependencies;
this.attachmentHelper = attachmentHelper;
this.sendHelper = sendHelper;
this.groupV2Helper = groupV2Helper;
this.avatarStore = avatarStore;
this.addressResolver = addressResolver;
this.recipientResolver = recipientResolver;
} }
public GroupInfo getGroup(GroupId groupId) { public GroupInfo getGroup(GroupId groupId) {
@ -101,15 +80,16 @@ public class GroupHelper {
public void downloadGroupAvatar(GroupIdV1 groupId, SignalServiceAttachment avatar) { public void downloadGroupAvatar(GroupIdV1 groupId, SignalServiceAttachment avatar) {
try { try {
avatarStore.storeGroupAvatar(groupId, context.getAvatarStore()
outputStream -> attachmentHelper.retrieveAttachment(avatar, outputStream)); .storeGroupAvatar(groupId,
outputStream -> context.getAttachmentHelper().retrieveAttachment(avatar, outputStream));
} catch (IOException e) { } catch (IOException e) {
logger.warn("Failed to download avatar for group {}, ignoring: {}", groupId.toBase64(), e.getMessage()); logger.warn("Failed to download avatar for group {}, ignoring: {}", groupId.toBase64(), e.getMessage());
} }
} }
public Optional<SignalServiceAttachmentStream> createGroupAvatarAttachment(GroupIdV1 groupId) throws IOException { public Optional<SignalServiceAttachmentStream> createGroupAvatarAttachment(GroupIdV1 groupId) throws IOException {
final var streamDetails = avatarStore.retrieveGroupAvatar(groupId); final var streamDetails = context.getAvatarStore().retrieveGroupAvatar(groupId);
if (streamDetails == null) { if (streamDetails == null) {
return Optional.absent(); return Optional.absent();
} }
@ -143,13 +123,12 @@ public class GroupHelper {
if (signedGroupChange != null if (signedGroupChange != null
&& groupInfoV2.getGroup() != null && groupInfoV2.getGroup() != null
&& groupInfoV2.getGroup().getRevision() + 1 == revision) { && groupInfoV2.getGroup().getRevision() + 1 == revision) {
group = groupV2Helper.getUpdatedDecryptedGroup(groupInfoV2.getGroup(), group = context.getGroupV2Helper()
signedGroupChange, .getUpdatedDecryptedGroup(groupInfoV2.getGroup(), signedGroupChange, groupMasterKey);
groupMasterKey);
} }
if (group == null) { if (group == null) {
try { try {
group = groupV2Helper.getDecryptedGroup(groupSecretParams); group = context.getGroupV2Helper().getDecryptedGroup(groupSecretParams);
} catch (NotAGroupMemberException ignored) { } catch (NotAGroupMemberException ignored) {
} }
} }
@ -160,7 +139,7 @@ public class GroupHelper {
downloadGroupAvatar(groupId, groupSecretParams, avatar); downloadGroupAvatar(groupId, groupSecretParams, avatar);
} }
} }
groupInfoV2.setGroup(group, recipientResolver); groupInfoV2.setGroup(group, account.getRecipientStore());
account.getGroupStore().updateGroup(groupInfoV2); account.getGroupStore().updateGroup(groupInfoV2);
} }
@ -176,9 +155,8 @@ public class GroupHelper {
members.remove(selfRecipientId); members.remove(selfRecipientId);
} }
var gv2Pair = groupV2Helper.createGroup(name == null ? "" : name, var gv2Pair = context.getGroupV2Helper()
members == null ? Set.of() : members, .createGroup(name == null ? "" : name, members == null ? Set.of() : members, avatarFile);
avatarFile);
if (gv2Pair == null) { if (gv2Pair == null) {
// Failed to create v2 group, creating v1 group instead // Failed to create v2 group, creating v1 group instead
@ -191,10 +169,11 @@ public class GroupHelper {
final var gv2 = gv2Pair.first(); final var gv2 = gv2Pair.first();
final var decryptedGroup = gv2Pair.second(); final var decryptedGroup = gv2Pair.second();
gv2.setGroup(decryptedGroup, recipientResolver); gv2.setGroup(decryptedGroup, account.getRecipientStore());
if (avatarFile != null) { if (avatarFile != null) {
avatarStore.storeGroupAvatar(gv2.getGroupId(), context.getAvatarStore()
outputStream -> IOUtils.copyFileToStream(avatarFile, outputStream)); .storeGroupAvatar(gv2.getGroupId(),
outputStream -> IOUtils.copyFileToStream(avatarFile, outputStream));
} }
account.getGroupStore().updateGroup(gv2); account.getGroupStore().updateGroup(gv2);
@ -274,14 +253,13 @@ public class GroupHelper {
) throws IOException, InactiveGroupLinkException { ) throws IOException, InactiveGroupLinkException {
final DecryptedGroupJoinInfo groupJoinInfo; final DecryptedGroupJoinInfo groupJoinInfo;
try { try {
groupJoinInfo = groupV2Helper.getDecryptedGroupJoinInfo(inviteLinkUrl.getGroupMasterKey(), groupJoinInfo = context.getGroupV2Helper()
inviteLinkUrl.getPassword()); .getDecryptedGroupJoinInfo(inviteLinkUrl.getGroupMasterKey(), inviteLinkUrl.getPassword());
} catch (GroupLinkNotActiveException e) { } catch (GroupLinkNotActiveException e) {
throw new InactiveGroupLinkException("Group link inactive", e); throw new InactiveGroupLinkException("Group link inactive", e);
} }
final var groupChange = groupV2Helper.joinGroup(inviteLinkUrl.getGroupMasterKey(), final var groupChange = context.getGroupV2Helper()
inviteLinkUrl.getPassword(), .joinGroup(inviteLinkUrl.getGroupMasterKey(), inviteLinkUrl.getPassword(), groupJoinInfo);
groupJoinInfo);
final var group = getOrMigrateGroup(inviteLinkUrl.getGroupMasterKey(), final var group = getOrMigrateGroup(inviteLinkUrl.getGroupMasterKey(),
groupJoinInfo.getRevision() + 1, groupJoinInfo.getRevision() + 1,
groupChange.toByteArray()); groupChange.toByteArray());
@ -315,7 +293,7 @@ public class GroupHelper {
public void deleteGroup(GroupId groupId) throws IOException { public void deleteGroup(GroupId groupId) throws IOException {
account.getGroupStore().deleteGroup(groupId); account.getGroupStore().deleteGroup(groupId);
avatarStore.deleteGroupAvatar(groupId); context.getAvatarStore().deleteGroupAvatar(groupId);
} }
public void setGroupBlocked(final GroupId groupId, final boolean blocked) throws GroupNotFoundException { public void setGroupBlocked(final GroupId groupId, final boolean blocked) throws GroupNotFoundException {
@ -366,12 +344,12 @@ public class GroupHelper {
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
DecryptedGroup decryptedGroup; DecryptedGroup decryptedGroup;
try { try {
decryptedGroup = groupV2Helper.getDecryptedGroup(groupSecretParams); decryptedGroup = context.getGroupV2Helper().getDecryptedGroup(groupSecretParams);
} catch (NotAGroupMemberException e) { } catch (NotAGroupMemberException e) {
groupInfoV2.setPermissionDenied(true); groupInfoV2.setPermissionDenied(true);
decryptedGroup = null; decryptedGroup = null;
} }
groupInfoV2.setGroup(decryptedGroup, recipientResolver); groupInfoV2.setGroup(decryptedGroup, account.getRecipientStore());
account.getGroupStore().updateGroup(group); account.getGroupStore().updateGroup(group);
} }
} }
@ -380,8 +358,9 @@ public class GroupHelper {
private void downloadGroupAvatar(GroupIdV2 groupId, GroupSecretParams groupSecretParams, String cdnKey) { private void downloadGroupAvatar(GroupIdV2 groupId, GroupSecretParams groupSecretParams, String cdnKey) {
try { try {
avatarStore.storeGroupAvatar(groupId, context.getAvatarStore()
outputStream -> retrieveGroupV2Avatar(groupSecretParams, cdnKey, outputStream)); .storeGroupAvatar(groupId,
outputStream -> retrieveGroupV2Avatar(groupSecretParams, cdnKey, outputStream));
} catch (IOException e) { } catch (IOException e) {
logger.warn("Failed to download avatar for group {}, ignoring: {}", groupId.toBase64(), e.getMessage()); logger.warn("Failed to download avatar for group {}, ignoring: {}", groupId.toBase64(), e.getMessage());
} }
@ -458,8 +437,9 @@ public class GroupHelper {
} }
if (avatarFile != null) { if (avatarFile != null) {
avatarStore.storeGroupAvatar(g.getGroupId(), context.getAvatarStore()
outputStream -> IOUtils.copyFileToStream(avatarFile, outputStream)); .storeGroupAvatar(g.getGroupId(),
outputStream -> IOUtils.copyFileToStream(avatarFile, outputStream));
} }
} }
@ -476,7 +456,7 @@ public class GroupHelper {
private void sendExpirationTimerUpdate(GroupIdV1 groupId) throws IOException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException { private void sendExpirationTimerUpdate(GroupIdV1 groupId) throws IOException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException {
final var messageBuilder = SignalServiceDataMessage.newBuilder().asExpirationUpdate(); final var messageBuilder = SignalServiceDataMessage.newBuilder().asExpirationUpdate();
sendHelper.sendAsGroupMessage(messageBuilder, groupId); context.getSendHelper().sendAsGroupMessage(messageBuilder, groupId);
} }
private SendGroupMessageResults updateGroupV2( private SendGroupMessageResults updateGroupV2(
@ -496,6 +476,7 @@ public class GroupHelper {
final Boolean isAnnouncementGroup final Boolean isAnnouncementGroup
) throws IOException { ) throws IOException {
SendGroupMessageResults result = null; SendGroupMessageResults result = null;
final var groupV2Helper = context.getGroupV2Helper();
if (group.isPendingMember(account.getSelfRecipientId())) { if (group.isPendingMember(account.getSelfRecipientId())) {
var groupGroupChangePair = groupV2Helper.acceptInvite(group); var groupGroupChangePair = groupV2Helper.acceptInvite(group);
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second()); result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
@ -587,8 +568,9 @@ public class GroupHelper {
if (name != null || description != null || avatarFile != null) { if (name != null || description != null || avatarFile != null) {
var groupGroupChangePair = groupV2Helper.updateGroup(group, name, description, avatarFile); var groupGroupChangePair = groupV2Helper.updateGroup(group, name, description, avatarFile);
if (avatarFile != null) { if (avatarFile != null) {
avatarStore.storeGroupAvatar(group.getGroupId(), context.getAvatarStore()
outputStream -> IOUtils.copyFileToStream(avatarFile, outputStream)); .storeGroupAvatar(group.getGroupId(),
outputStream -> IOUtils.copyFileToStream(avatarFile, outputStream));
} }
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second()); result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
} }
@ -622,8 +604,8 @@ public class GroupHelper {
// Last admin can't leave the group, unless she's also the last member // Last admin can't leave the group, unless she's also the last member
throw new LastGroupAdminException(groupInfoV2.getGroupId(), groupInfoV2.getTitle()); throw new LastGroupAdminException(groupInfoV2.getGroupId(), groupInfoV2.getTitle());
} }
final var groupGroupChangePair = groupV2Helper.leaveGroup(groupInfoV2, newAdmins); final var groupGroupChangePair = context.getGroupV2Helper().leaveGroup(groupInfoV2, newAdmins);
groupInfoV2.setGroup(groupGroupChangePair.first(), recipientResolver); groupInfoV2.setGroup(groupGroupChangePair.first(), account.getRecipientStore());
account.getGroupStore().updateGroup(groupInfoV2); account.getGroupStore().updateGroup(groupInfoV2);
var messageBuilder = getGroupUpdateMessageBuilder(groupInfoV2, groupGroupChangePair.second().toByteArray()); var messageBuilder = getGroupUpdateMessageBuilder(groupInfoV2, groupGroupChangePair.second().toByteArray());
@ -636,7 +618,10 @@ public class GroupHelper {
var group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.UPDATE) var group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.UPDATE)
.withId(g.getGroupId().serialize()) .withId(g.getGroupId().serialize())
.withName(g.name) .withName(g.name)
.withMembers(g.getMembers().stream().map(addressResolver::resolveSignalServiceAddress).toList()); .withMembers(g.getMembers()
.stream()
.map(context.getRecipientHelper()::resolveSignalServiceAddress)
.toList());
try { try {
final var attachment = createGroupAvatarAttachment(g.getGroupId()); final var attachment = createGroupAvatarAttachment(g.getGroupId());
@ -666,7 +651,7 @@ public class GroupHelper {
) throws IOException { ) throws IOException {
final var selfRecipientId = account.getSelfRecipientId(); final var selfRecipientId = account.getSelfRecipientId();
final var members = group.getMembersIncludingPendingWithout(selfRecipientId); final var members = group.getMembersIncludingPendingWithout(selfRecipientId);
group.setGroup(newDecryptedGroup, recipientResolver); group.setGroup(newDecryptedGroup, account.getRecipientStore());
members.addAll(group.getMembersIncludingPendingWithout(selfRecipientId)); members.addAll(group.getMembersIncludingPendingWithout(selfRecipientId));
account.getGroupStore().updateGroup(group); account.getGroupStore().updateGroup(group);
@ -681,11 +666,11 @@ public class GroupHelper {
) throws IOException { ) throws IOException {
final var timestamp = System.currentTimeMillis(); final var timestamp = System.currentTimeMillis();
messageBuilder.withTimestamp(timestamp); messageBuilder.withTimestamp(timestamp);
final var results = sendHelper.sendGroupMessage(messageBuilder.build(), members, distributionId); final var results = context.getSendHelper().sendGroupMessage(messageBuilder.build(), members, distributionId);
return new SendGroupMessageResults(timestamp, return new SendGroupMessageResults(timestamp,
results.stream() results.stream()
.map(sendMessageResult -> SendMessageResult.from(sendMessageResult, .map(sendMessageResult -> SendMessageResult.from(sendMessageResult,
recipientResolver, account.getRecipientStore(),
account.getRecipientStore()::resolveRecipientAddress)) account.getRecipientStore()::resolveRecipientAddress))
.toList()); .toList());
} }

View file

@ -1,9 +0,0 @@
package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.groups.GroupId;
import org.asamk.signal.manager.storage.groups.GroupInfo;
public interface GroupProvider {
GroupInfo getGroup(GroupId groupId);
}

View file

@ -2,6 +2,7 @@ package org.asamk.signal.manager.helper;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import org.asamk.signal.manager.SignalDependencies;
import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.Pair;
import org.asamk.signal.manager.groups.GroupLinkPassword; import org.asamk.signal.manager.groups.GroupLinkPassword;
import org.asamk.signal.manager.groups.GroupLinkState; import org.asamk.signal.manager.groups.GroupLinkState;
@ -32,7 +33,6 @@ import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil;
import org.whispersystems.signalservice.api.groupsv2.GroupCandidate; import org.whispersystems.signalservice.api.groupsv2.GroupCandidate;
import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException; import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString; import org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations; import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException; import org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException;
@ -56,32 +56,20 @@ public class GroupV2Helper {
private final static Logger logger = LoggerFactory.getLogger(GroupV2Helper.class); private final static Logger logger = LoggerFactory.getLogger(GroupV2Helper.class);
private final ProfileHelper profileHelper; private final SignalDependencies dependencies;
private final SelfRecipientIdProvider selfRecipientIdProvider; private final Context context;
private final GroupsV2Operations groupsV2Operations;
private final GroupsV2Api groupsV2Api;
private final SignalServiceAddressResolver addressResolver;
private HashMap<Integer, AuthCredentialResponse> groupApiCredentials; private HashMap<Integer, AuthCredentialResponse> groupApiCredentials;
public GroupV2Helper( public GroupV2Helper(final Context context) {
final ProfileHelper profileHelper, this.dependencies = context.getDependencies();
final SelfRecipientIdProvider selfRecipientIdProvider, this.context = context;
final GroupsV2Operations groupsV2Operations,
final GroupsV2Api groupsV2Api,
final SignalServiceAddressResolver addressResolver
) {
this.profileHelper = profileHelper;
this.selfRecipientIdProvider = selfRecipientIdProvider;
this.groupsV2Operations = groupsV2Operations;
this.groupsV2Api = groupsV2Api;
this.addressResolver = addressResolver;
} }
public DecryptedGroup getDecryptedGroup(final GroupSecretParams groupSecretParams) throws NotAGroupMemberException { public DecryptedGroup getDecryptedGroup(final GroupSecretParams groupSecretParams) throws NotAGroupMemberException {
try { try {
final var groupsV2AuthorizationString = getGroupAuthForToday(groupSecretParams); final var groupsV2AuthorizationString = getGroupAuthForToday(groupSecretParams);
return groupsV2Api.getGroup(groupSecretParams, groupsV2AuthorizationString); return dependencies.getGroupsV2Api().getGroup(groupSecretParams, groupsV2AuthorizationString);
} catch (NonSuccessfulResponseCodeException e) { } catch (NonSuccessfulResponseCodeException e) {
if (e.getCode() == 403) { if (e.getCode() == 403) {
throw new NotAGroupMemberException(GroupUtils.getGroupIdV2(groupSecretParams), null); throw new NotAGroupMemberException(GroupUtils.getGroupIdV2(groupSecretParams), null);
@ -99,9 +87,10 @@ public class GroupV2Helper {
) throws IOException, GroupLinkNotActiveException { ) throws IOException, GroupLinkNotActiveException {
var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey);
return groupsV2Api.getGroupJoinInfo(groupSecretParams, return dependencies.getGroupsV2Api()
Optional.fromNullable(password).transform(GroupLinkPassword::serialize), .getGroupJoinInfo(groupSecretParams,
getGroupAuthForToday(groupSecretParams)); Optional.fromNullable(password).transform(GroupLinkPassword::serialize),
getGroupAuthForToday(groupSecretParams));
} }
public Pair<GroupInfoV2, DecryptedGroup> createGroup( public Pair<GroupInfoV2, DecryptedGroup> createGroup(
@ -119,8 +108,8 @@ public class GroupV2Helper {
final DecryptedGroup decryptedGroup; final DecryptedGroup decryptedGroup;
try { try {
groupAuthForToday = getGroupAuthForToday(groupSecretParams); groupAuthForToday = getGroupAuthForToday(groupSecretParams);
groupsV2Api.putNewGroup(newGroup, groupAuthForToday); dependencies.getGroupsV2Api().putNewGroup(newGroup, groupAuthForToday);
decryptedGroup = groupsV2Api.getGroup(groupSecretParams, groupAuthForToday); decryptedGroup = dependencies.getGroupsV2Api().getGroup(groupSecretParams, groupAuthForToday);
} catch (IOException | VerificationFailedException | InvalidGroupStateException e) { } catch (IOException | VerificationFailedException | InvalidGroupStateException e) {
logger.warn("Failed to create V2 group: {}", e.getMessage()); logger.warn("Failed to create V2 group: {}", e.getMessage());
return null; return null;
@ -148,7 +137,8 @@ public class GroupV2Helper {
private GroupsV2Operations.NewGroup buildNewGroup( private GroupsV2Operations.NewGroup buildNewGroup(
String name, Set<RecipientId> members, byte[] avatar String name, Set<RecipientId> members, byte[] avatar
) { ) {
final var profileKeyCredential = profileHelper.getRecipientProfileKeyCredential(selfRecipientIdProvider.getSelfRecipientId()); final var profileKeyCredential = context.getProfileHelper()
.getRecipientProfileKeyCredential(context.getAccount().getSelfRecipientId());
if (profileKeyCredential == null) { if (profileKeyCredential == null) {
logger.warn("Cannot create a V2 group as self does not have a versioned profile"); logger.warn("Cannot create a V2 group as self does not have a versioned profile");
return null; return null;
@ -158,26 +148,28 @@ public class GroupV2Helper {
final var self = new GroupCandidate(getSelfAci().uuid(), Optional.fromNullable(profileKeyCredential)); final var self = new GroupCandidate(getSelfAci().uuid(), Optional.fromNullable(profileKeyCredential));
final var memberList = new ArrayList<>(members); final var memberList = new ArrayList<>(members);
final var credentials = profileHelper.getRecipientProfileKeyCredential(memberList).stream(); final var credentials = context.getProfileHelper().getRecipientProfileKeyCredential(memberList).stream();
final var uuids = memberList.stream() final var uuids = memberList.stream()
.map(member -> addressResolver.resolveSignalServiceAddress(member).getAci().uuid()); .map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getAci().uuid());
var candidates = Utils.zip(uuids, var candidates = Utils.zip(uuids,
credentials, credentials,
(uuid, credential) -> new GroupCandidate(uuid, Optional.fromNullable(credential))) (uuid, credential) -> new GroupCandidate(uuid, Optional.fromNullable(credential)))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
final var groupSecretParams = GroupSecretParams.generate(); final var groupSecretParams = GroupSecretParams.generate();
return groupsV2Operations.createNewGroup(groupSecretParams, return dependencies.getGroupsV2Operations()
name, .createNewGroup(groupSecretParams,
Optional.fromNullable(avatar), name,
self, Optional.fromNullable(avatar),
candidates, self,
Member.Role.DEFAULT, candidates,
0); Member.Role.DEFAULT,
0);
} }
private boolean areMembersValid(final Set<RecipientId> members) { private boolean areMembersValid(final Set<RecipientId> members) {
final var noGv2Capability = profileHelper.getRecipientProfile(new ArrayList<>(members)) final var noGv2Capability = context.getProfileHelper()
.getRecipientProfile(new ArrayList<>(members))
.stream() .stream()
.filter(profile -> profile != null && !profile.getCapabilities().contains(Profile.Capability.gv2)) .filter(profile -> profile != null && !profile.getCapabilities().contains(Profile.Capability.gv2))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
@ -194,7 +186,7 @@ public class GroupV2Helper {
GroupInfoV2 groupInfoV2, String name, String description, File avatarFile GroupInfoV2 groupInfoV2, String name, String description, File avatarFile
) throws IOException { ) throws IOException {
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
var groupOperations = groupsV2Operations.forGroup(groupSecretParams); var groupOperations = dependencies.getGroupsV2Operations().forGroup(groupSecretParams);
var change = name != null ? groupOperations.createModifyGroupTitle(name) : GroupChange.Actions.newBuilder(); var change = name != null ? groupOperations.createModifyGroupTitle(name) : GroupChange.Actions.newBuilder();
@ -204,9 +196,8 @@ public class GroupV2Helper {
if (avatarFile != null) { if (avatarFile != null) {
final var avatarBytes = readAvatarBytes(avatarFile); final var avatarBytes = readAvatarBytes(avatarFile);
var avatarCdnKey = groupsV2Api.uploadAvatar(avatarBytes, var avatarCdnKey = dependencies.getGroupsV2Api()
groupSecretParams, .uploadAvatar(avatarBytes, groupSecretParams, getGroupAuthForToday(groupSecretParams));
getGroupAuthForToday(groupSecretParams));
change.setModifyAvatar(GroupChange.Actions.ModifyAvatarAction.newBuilder().setAvatar(avatarCdnKey)); change.setModifyAvatar(GroupChange.Actions.ModifyAvatarAction.newBuilder().setAvatar(avatarCdnKey));
} }
@ -225,9 +216,9 @@ public class GroupV2Helper {
} }
final var memberList = new ArrayList<>(newMembers); final var memberList = new ArrayList<>(newMembers);
final var credentials = profileHelper.getRecipientProfileKeyCredential(memberList).stream(); final var credentials = context.getProfileHelper().getRecipientProfileKeyCredential(memberList).stream();
final var uuids = memberList.stream() final var uuids = memberList.stream()
.map(member -> addressResolver.resolveSignalServiceAddress(member).getAci().uuid()); .map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getAci().uuid());
var candidates = Utils.zip(uuids, var candidates = Utils.zip(uuids,
credentials, credentials,
(uuid, credential) -> new GroupCandidate(uuid, Optional.fromNullable(credential))) (uuid, credential) -> new GroupCandidate(uuid, Optional.fromNullable(credential)))
@ -253,7 +244,7 @@ public class GroupV2Helper {
} }
final var adminUuids = membersToMakeAdmin.stream() final var adminUuids = membersToMakeAdmin.stream()
.map(addressResolver::resolveSignalServiceAddress) .map(context.getRecipientHelper()::resolveSignalServiceAddress)
.map(SignalServiceAddress::getAci) .map(SignalServiceAddress::getAci)
.map(ACI::uuid) .map(ACI::uuid)
.toList(); .toList();
@ -266,7 +257,7 @@ public class GroupV2Helper {
GroupInfoV2 groupInfoV2, Set<RecipientId> members GroupInfoV2 groupInfoV2, Set<RecipientId> members
) throws IOException { ) throws IOException {
final var memberUuids = members.stream() final var memberUuids = members.stream()
.map(addressResolver::resolveSignalServiceAddress) .map(context.getRecipientHelper()::resolveSignalServiceAddress)
.map(SignalServiceAddress::getAci) .map(SignalServiceAddress::getAci)
.map(ACI::uuid) .map(ACI::uuid)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
@ -278,7 +269,7 @@ public class GroupV2Helper {
) throws IOException { ) throws IOException {
var pendingMembersList = groupInfoV2.getGroup().getPendingMembersList(); var pendingMembersList = groupInfoV2.getGroup().getPendingMembersList();
final var memberUuids = members.stream() final var memberUuids = members.stream()
.map(addressResolver::resolveSignalServiceAddress) .map(context.getRecipientHelper()::resolveSignalServiceAddress)
.map(SignalServiceAddress::getAci) .map(SignalServiceAddress::getAci)
.map(ACI::uuid) .map(ACI::uuid)
.map(uuid -> DecryptedGroupUtil.findPendingByUuid(pendingMembersList, uuid)) .map(uuid -> DecryptedGroupUtil.findPendingByUuid(pendingMembersList, uuid))
@ -337,10 +328,10 @@ public class GroupV2Helper {
DecryptedGroupJoinInfo decryptedGroupJoinInfo DecryptedGroupJoinInfo decryptedGroupJoinInfo
) throws IOException { ) throws IOException {
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey); final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupMasterKey);
final var groupOperations = groupsV2Operations.forGroup(groupSecretParams); final var groupOperations = dependencies.getGroupsV2Operations().forGroup(groupSecretParams);
final var selfRecipientId = this.selfRecipientIdProvider.getSelfRecipientId(); final var selfRecipientId = context.getAccount().getSelfRecipientId();
final var profileKeyCredential = profileHelper.getRecipientProfileKeyCredential(selfRecipientId); final var profileKeyCredential = context.getProfileHelper().getRecipientProfileKeyCredential(selfRecipientId);
if (profileKeyCredential == null) { if (profileKeyCredential == null) {
throw new IOException("Cannot join a V2 group as self does not have a versioned profile"); throw new IOException("Cannot join a V2 group as self does not have a versioned profile");
} }
@ -350,7 +341,10 @@ public class GroupV2Helper {
? groupOperations.createGroupJoinRequest(profileKeyCredential) ? groupOperations.createGroupJoinRequest(profileKeyCredential)
: groupOperations.createGroupJoinDirect(profileKeyCredential); : groupOperations.createGroupJoinDirect(profileKeyCredential);
change.setSourceUuid(addressResolver.resolveSignalServiceAddress(selfRecipientId).getAci().toByteString()); change.setSourceUuid(context.getRecipientHelper()
.resolveSignalServiceAddress(selfRecipientId)
.getAci()
.toByteString());
return commitChange(groupSecretParams, decryptedGroupJoinInfo.getRevision(), change, groupLinkPassword); return commitChange(groupSecretParams, decryptedGroupJoinInfo.getRevision(), change, groupLinkPassword);
} }
@ -358,15 +352,15 @@ public class GroupV2Helper {
public Pair<DecryptedGroup, GroupChange> acceptInvite(GroupInfoV2 groupInfoV2) throws IOException { public Pair<DecryptedGroup, GroupChange> acceptInvite(GroupInfoV2 groupInfoV2) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2); final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
final var selfRecipientId = this.selfRecipientIdProvider.getSelfRecipientId(); final var selfRecipientId = context.getAccount().getSelfRecipientId();
final var profileKeyCredential = profileHelper.getRecipientProfileKeyCredential(selfRecipientId); final var profileKeyCredential = context.getProfileHelper().getRecipientProfileKeyCredential(selfRecipientId);
if (profileKeyCredential == null) { if (profileKeyCredential == null) {
throw new IOException("Cannot join a V2 group as self does not have a versioned profile"); throw new IOException("Cannot join a V2 group as self does not have a versioned profile");
} }
final var change = groupOperations.createAcceptInviteChange(profileKeyCredential); final var change = groupOperations.createAcceptInviteChange(profileKeyCredential);
final var aci = addressResolver.resolveSignalServiceAddress(selfRecipientId).getAci(); final var aci = context.getRecipientHelper().resolveSignalServiceAddress(selfRecipientId).getAci();
change.setSourceUuid(aci.toByteString()); change.setSourceUuid(aci.toByteString());
return commitChange(groupInfoV2, change); return commitChange(groupInfoV2, change);
@ -376,7 +370,7 @@ public class GroupV2Helper {
GroupInfoV2 groupInfoV2, RecipientId recipientId, boolean admin GroupInfoV2 groupInfoV2, RecipientId recipientId, boolean admin
) throws IOException { ) throws IOException {
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2); final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
final var address = addressResolver.resolveSignalServiceAddress(recipientId); final var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId);
final var newRole = admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT; final var newRole = admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT;
final var change = groupOperations.createChangeMemberRole(address.getAci().uuid(), newRole); final var change = groupOperations.createChangeMemberRole(address.getAci().uuid(), newRole);
return commitChange(groupInfoV2, change); return commitChange(groupInfoV2, change);
@ -415,7 +409,7 @@ public class GroupV2Helper {
private GroupsV2Operations.GroupOperations getGroupOperations(final GroupInfoV2 groupInfoV2) { private GroupsV2Operations.GroupOperations getGroupOperations(final GroupInfoV2 groupInfoV2) {
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
return groupsV2Operations.forGroup(groupSecretParams); return dependencies.getGroupsV2Operations().forGroup(groupSecretParams);
} }
private Pair<DecryptedGroup, GroupChange> revokeInvites( private Pair<DecryptedGroup, GroupChange> revokeInvites(
@ -443,7 +437,7 @@ public class GroupV2Helper {
GroupInfoV2 groupInfoV2, GroupChange.Actions.Builder change GroupInfoV2 groupInfoV2, GroupChange.Actions.Builder change
) throws IOException { ) throws IOException {
final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey());
final var groupOperations = groupsV2Operations.forGroup(groupSecretParams); final var groupOperations = dependencies.getGroupsV2Operations().forGroup(groupSecretParams);
final var previousGroupState = groupInfoV2.getGroup(); final var previousGroupState = groupInfoV2.getGroup();
final var nextRevision = previousGroupState.getRevision() + 1; final var nextRevision = previousGroupState.getRevision() + 1;
final var changeActions = change.setRevision(nextRevision).build(); final var changeActions = change.setRevision(nextRevision).build();
@ -457,9 +451,8 @@ public class GroupV2Helper {
throw new IOException(e); throw new IOException(e);
} }
var signedGroupChange = groupsV2Api.patchGroup(changeActions, var signedGroupChange = dependencies.getGroupsV2Api()
getGroupAuthForToday(groupSecretParams), .patchGroup(changeActions, getGroupAuthForToday(groupSecretParams), Optional.absent());
Optional.absent());
return new Pair<>(decryptedGroupState, signedGroupChange); return new Pair<>(decryptedGroupState, signedGroupChange);
} }
@ -473,9 +466,10 @@ public class GroupV2Helper {
final var nextRevision = currentRevision + 1; final var nextRevision = currentRevision + 1;
final var changeActions = change.setRevision(nextRevision).build(); final var changeActions = change.setRevision(nextRevision).build();
return groupsV2Api.patchGroup(changeActions, return dependencies.getGroupsV2Api()
getGroupAuthForToday(groupSecretParams), .patchGroup(changeActions,
Optional.fromNullable(password).transform(GroupLinkPassword::serialize)); getGroupAuthForToday(groupSecretParams),
Optional.fromNullable(password).transform(GroupLinkPassword::serialize));
} }
public DecryptedGroup getUpdatedDecryptedGroup( public DecryptedGroup getUpdatedDecryptedGroup(
@ -494,7 +488,8 @@ public class GroupV2Helper {
private DecryptedGroupChange getDecryptedGroupChange(byte[] signedGroupChange, GroupMasterKey groupMasterKey) { private DecryptedGroupChange getDecryptedGroupChange(byte[] signedGroupChange, GroupMasterKey groupMasterKey) {
if (signedGroupChange != null) { if (signedGroupChange != null) {
var groupOperations = groupsV2Operations.forGroup(GroupSecretParams.deriveFromMasterKey(groupMasterKey)); var groupOperations = dependencies.getGroupsV2Operations()
.forGroup(GroupSecretParams.deriveFromMasterKey(groupMasterKey));
try { try {
return groupOperations.decryptChange(GroupChange.parseFrom(signedGroupChange), true).orNull(); return groupOperations.decryptChange(GroupChange.parseFrom(signedGroupChange), true).orNull();
@ -516,19 +511,20 @@ public class GroupV2Helper {
final var today = currentTimeDays(); final var today = currentTimeDays();
if (groupApiCredentials == null || !groupApiCredentials.containsKey(today)) { if (groupApiCredentials == null || !groupApiCredentials.containsKey(today)) {
// Returns credentials for the next 7 days // Returns credentials for the next 7 days
groupApiCredentials = groupsV2Api.getCredentials(today); groupApiCredentials = dependencies.getGroupsV2Api().getCredentials(today);
// TODO cache credentials on disk until they expire // TODO cache credentials on disk until they expire
} }
var authCredentialResponse = groupApiCredentials.get(today); var authCredentialResponse = groupApiCredentials.get(today);
final var aci = getSelfAci(); final var aci = getSelfAci();
try { try {
return groupsV2Api.getGroupsV2AuthorizationString(aci, today, groupSecretParams, authCredentialResponse); return dependencies.getGroupsV2Api()
.getGroupsV2AuthorizationString(aci, today, groupSecretParams, authCredentialResponse);
} catch (VerificationFailedException e) { } catch (VerificationFailedException e) {
throw new IOException(e); throw new IOException(e);
} }
} }
private ACI getSelfAci() { private ACI getSelfAci() {
return addressResolver.resolveSignalServiceAddress(this.selfRecipientIdProvider.getSelfRecipientId()).getAci(); return context.getAccount().getAci();
} }
} }

View file

@ -1,9 +0,0 @@
package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.storage.recipients.RecipientId;
import org.whispersystems.signalservice.api.messages.SendMessageResult;
public interface IdentityFailureHandler {
void handleIdentityFailure(RecipientId recipientId, SendMessageResult.IdentityFailure identityFailure);
}

View file

@ -1,6 +1,5 @@
package org.asamk.signal.manager.helper; package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.SignalDependencies;
import org.asamk.signal.manager.TrustLevel; import org.asamk.signal.manager.TrustLevel;
import org.asamk.signal.manager.storage.SignalAccount; import org.asamk.signal.manager.storage.SignalAccount;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
@ -27,23 +26,11 @@ public class IdentityHelper {
private final static Logger logger = LoggerFactory.getLogger(IdentityHelper.class); private final static Logger logger = LoggerFactory.getLogger(IdentityHelper.class);
private final SignalAccount account; private final SignalAccount account;
private final SignalDependencies dependencies; private final Context context;
private final SignalServiceAddressResolver addressResolver;
private final SyncHelper syncHelper;
private final ProfileHelper profileHelper;
public IdentityHelper( public IdentityHelper(final Context context) {
final SignalAccount account, this.account = context.getAccount();
final SignalDependencies dependencies, this.context = context;
final SignalServiceAddressResolver addressResolver,
final SyncHelper syncHelper,
final ProfileHelper profileHelper
) {
this.account = account;
this.dependencies = dependencies;
this.addressResolver = addressResolver;
this.syncHelper = syncHelper;
this.profileHelper = profileHelper;
} }
public boolean trustIdentityVerified(RecipientId recipientId, byte[] fingerprint) { public boolean trustIdentityVerified(RecipientId recipientId, byte[] fingerprint) {
@ -74,13 +61,13 @@ public class IdentityHelper {
} }
public String computeSafetyNumber(RecipientId recipientId, IdentityKey theirIdentityKey) { public String computeSafetyNumber(RecipientId recipientId, IdentityKey theirIdentityKey) {
var address = addressResolver.resolveSignalServiceAddress(recipientId); var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId);
final Fingerprint fingerprint = computeSafetyNumberFingerprint(address, theirIdentityKey); final Fingerprint fingerprint = computeSafetyNumberFingerprint(address, theirIdentityKey);
return fingerprint == null ? null : fingerprint.getDisplayableFingerprint().getDisplayText(); return fingerprint == null ? null : fingerprint.getDisplayableFingerprint().getDisplayText();
} }
public ScannableFingerprint computeSafetyNumberForScanning(RecipientId recipientId, IdentityKey theirIdentityKey) { public ScannableFingerprint computeSafetyNumberForScanning(RecipientId recipientId, IdentityKey theirIdentityKey) {
var address = addressResolver.resolveSignalServiceAddress(recipientId); var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId);
final Fingerprint fingerprint = computeSafetyNumberFingerprint(address, theirIdentityKey); final Fingerprint fingerprint = computeSafetyNumberFingerprint(address, theirIdentityKey);
return fingerprint == null ? null : fingerprint.getScannableFingerprint(); return fingerprint == null ? null : fingerprint.getScannableFingerprint();
} }
@ -109,8 +96,8 @@ public class IdentityHelper {
account.getIdentityKeyStore().setIdentityTrustLevel(recipientId, identity.getIdentityKey(), trustLevel); account.getIdentityKeyStore().setIdentityTrustLevel(recipientId, identity.getIdentityKey(), trustLevel);
try { try {
var address = addressResolver.resolveSignalServiceAddress(recipientId); var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId);
syncHelper.sendVerifiedMessage(address, identity.getIdentityKey(), trustLevel); context.getSyncHelper().sendVerifiedMessage(address, identity.getIdentityKey(), trustLevel);
} catch (IOException e) { } catch (IOException e) {
logger.warn("Failed to send verification sync message: {}", e.getMessage()); logger.warn("Failed to send verification sync message: {}", e.getMessage());
} }
@ -130,7 +117,7 @@ public class IdentityHelper {
} }
} else { } else {
// Retrieve profile to get the current identity key from the server // Retrieve profile to get the current identity key from the server
profileHelper.refreshRecipientProfile(recipientId); context.getProfileHelper().refreshRecipientProfile(recipientId);
} }
} }
} }

View file

@ -1,6 +1,5 @@
package org.asamk.signal.manager.helper; package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.JobExecutor;
import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.SignalDependencies; import org.asamk.signal.manager.SignalDependencies;
import org.asamk.signal.manager.TrustLevel; import org.asamk.signal.manager.TrustLevel;
@ -29,7 +28,6 @@ import org.asamk.signal.manager.storage.SignalAccount;
import org.asamk.signal.manager.storage.groups.GroupInfoV1; import org.asamk.signal.manager.storage.groups.GroupInfoV1;
import org.asamk.signal.manager.storage.recipients.Profile; import org.asamk.signal.manager.storage.recipients.Profile;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
import org.asamk.signal.manager.storage.stickers.Sticker; import org.asamk.signal.manager.storage.stickers.Sticker;
import org.asamk.signal.manager.storage.stickers.StickerPackId; import org.asamk.signal.manager.storage.stickers.StickerPackId;
import org.signal.libsignal.metadata.ProtocolInvalidKeyException; import org.signal.libsignal.metadata.ProtocolInvalidKeyException;
@ -61,37 +59,12 @@ public final class IncomingMessageHandler {
private final SignalAccount account; private final SignalAccount account;
private final SignalDependencies dependencies; private final SignalDependencies dependencies;
private final RecipientResolver recipientResolver; private final Context context;
private final SignalServiceAddressResolver addressResolver;
private final GroupHelper groupHelper;
private final ContactHelper contactHelper;
private final AttachmentHelper attachmentHelper;
private final SyncHelper syncHelper;
private final ProfileProvider profileProvider;
private final JobExecutor jobExecutor;
public IncomingMessageHandler( public IncomingMessageHandler(final Context context) {
final SignalAccount account, this.account = context.getAccount();
final SignalDependencies dependencies, this.dependencies = context.getDependencies();
final RecipientResolver recipientResolver, this.context = context;
final SignalServiceAddressResolver addressResolver,
final GroupHelper groupHelper,
final ContactHelper contactHelper,
final AttachmentHelper attachmentHelper,
final SyncHelper syncHelper,
final ProfileProvider profileProvider,
final JobExecutor jobExecutor
) {
this.account = account;
this.dependencies = dependencies;
this.recipientResolver = recipientResolver;
this.addressResolver = addressResolver;
this.groupHelper = groupHelper;
this.contactHelper = contactHelper;
this.attachmentHelper = attachmentHelper;
this.syncHelper = syncHelper;
this.profileProvider = profileProvider;
this.jobExecutor = jobExecutor;
} }
public Pair<List<HandleAction>, Exception> handleRetryEnvelope( public Pair<List<HandleAction>, Exception> handleRetryEnvelope(
@ -147,8 +120,8 @@ public final class IncomingMessageHandler {
.resolveRecipientAddress(recipientId), e.getSenderDevice()); .resolveRecipientAddress(recipientId), e.getSenderDevice());
} catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolNoSessionException | ProtocolInvalidMessageException e) { } catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolNoSessionException | ProtocolInvalidMessageException e) {
final var sender = account.getRecipientStore().resolveRecipient(e.getSender()); final var sender = account.getRecipientStore().resolveRecipient(e.getSender());
final var senderProfile = profileProvider.getProfile(sender); final var senderProfile = context.getProfileHelper().getRecipientProfile(sender);
final var selfProfile = profileProvider.getProfile(account.getSelfRecipientId()); final var selfProfile = context.getProfileHelper().getRecipientProfile(account.getSelfRecipientId());
if (e.getSenderDevice() != account.getDeviceId() if (e.getSenderDevice() != account.getDeviceId()
&& senderProfile != null && senderProfile != null
&& senderProfile.getCapabilities().contains(Profile.Capability.senderKey) && senderProfile.getCapabilities().contains(Profile.Capability.senderKey)
@ -202,9 +175,9 @@ public final class IncomingMessageHandler {
} }
handler.handleMessage(MessageEnvelope.from(envelope, handler.handleMessage(MessageEnvelope.from(envelope,
content, content,
recipientResolver, account.getRecipientStore(),
account.getRecipientStore()::resolveRecipientAddress, account.getRecipientStore()::resolveRecipientAddress,
attachmentHelper::getAttachmentFile), exception); context.getAttachmentHelper()::getAttachmentFile), exception);
return actions; return actions;
} }
} }
@ -216,16 +189,17 @@ public final class IncomingMessageHandler {
final RecipientId sender; final RecipientId sender;
final int senderDeviceId; final int senderDeviceId;
if (!envelope.isUnidentifiedSender() && envelope.hasSourceUuid()) { if (!envelope.isUnidentifiedSender() && envelope.hasSourceUuid()) {
sender = recipientResolver.resolveRecipient(envelope.getSourceAddress()); sender = context.getRecipientHelper().resolveRecipient(envelope.getSourceAddress());
senderDeviceId = envelope.getSourceDevice(); senderDeviceId = envelope.getSourceDevice();
} else { } else {
sender = recipientResolver.resolveRecipient(content.getSender()); sender = context.getRecipientHelper().resolveRecipient(content.getSender());
senderDeviceId = content.getSenderDevice(); senderDeviceId = content.getSenderDevice();
} }
if (content.getSenderKeyDistributionMessage().isPresent()) { if (content.getSenderKeyDistributionMessage().isPresent()) {
final var message = content.getSenderKeyDistributionMessage().get(); final var message = content.getSenderKeyDistributionMessage().get();
final var protocolAddress = new SignalProtocolAddress(addressResolver.resolveSignalServiceAddress(sender) final var protocolAddress = new SignalProtocolAddress(context.getRecipientHelper()
.resolveSignalServiceAddress(sender)
.getIdentifier(), senderDeviceId); .getIdentifier(), senderDeviceId);
logger.debug("Received a sender key distribution message for distributionId {} from {}", logger.debug("Received a sender key distribution message for distributionId {} from {}",
message.getDistributionId(), message.getDistributionId(),
@ -281,7 +255,7 @@ public final class IncomingMessageHandler {
actions.addAll(handleSignalServiceDataMessage(message.getMessage(), actions.addAll(handleSignalServiceDataMessage(message.getMessage(),
true, true,
sender, sender,
destination == null ? null : recipientResolver.resolveRecipient(destination), destination == null ? null : context.getRecipientHelper().resolveRecipient(destination),
ignoreAttachments)); ignoreAttachments));
} }
if (syncMessage.getRequest().isPresent() && account.isMasterDevice()) { if (syncMessage.getRequest().isPresent() && account.isMasterDevice()) {
@ -308,14 +282,15 @@ public final class IncomingMessageHandler {
if (syncMessage.getBlockedList().isPresent()) { if (syncMessage.getBlockedList().isPresent()) {
final var blockedListMessage = syncMessage.getBlockedList().get(); final var blockedListMessage = syncMessage.getBlockedList().get();
for (var address : blockedListMessage.getAddresses()) { for (var address : blockedListMessage.getAddresses()) {
contactHelper.setContactBlocked(recipientResolver.resolveRecipient(address), true); context.getContactHelper()
.setContactBlocked(context.getRecipientHelper().resolveRecipient(address), true);
} }
for (var groupId : blockedListMessage.getGroupIds() for (var groupId : blockedListMessage.getGroupIds()
.stream() .stream()
.map(GroupId::unknownVersion) .map(GroupId::unknownVersion)
.collect(Collectors.toSet())) { .collect(Collectors.toSet())) {
try { try {
groupHelper.setGroupBlocked(groupId, true); context.getGroupHelper().setGroupBlocked(groupId, true);
} catch (GroupNotFoundException e) { } catch (GroupNotFoundException e) {
logger.warn("BlockedListMessage contained groupID that was not found in GroupStore: {}", logger.warn("BlockedListMessage contained groupID that was not found in GroupStore: {}",
groupId.toBase64()); groupId.toBase64());
@ -325,8 +300,9 @@ public final class IncomingMessageHandler {
if (syncMessage.getContacts().isPresent()) { if (syncMessage.getContacts().isPresent()) {
try { try {
final var contactsMessage = syncMessage.getContacts().get(); final var contactsMessage = syncMessage.getContacts().get();
attachmentHelper.retrieveAttachment(contactsMessage.getContactsStream(), context.getAttachmentHelper()
syncHelper::handleSyncDeviceContacts); .retrieveAttachment(contactsMessage.getContactsStream(),
context.getSyncHelper()::handleSyncDeviceContacts);
} catch (Exception e) { } catch (Exception e) {
logger.warn("Failed to handle received sync contacts, ignoring: {}", e.getMessage()); logger.warn("Failed to handle received sync contacts, ignoring: {}", e.getMessage());
} }
@ -355,7 +331,8 @@ public final class IncomingMessageHandler {
sticker = new Sticker(stickerPackId, m.getPackKey().get()); sticker = new Sticker(stickerPackId, m.getPackKey().get());
} }
if (installed) { if (installed) {
jobExecutor.enqueueJob(new RetrieveStickerPackJob(stickerPackId, m.getPackKey().get())); context.getJobExecutor()
.enqueueJob(new RetrieveStickerPackJob(stickerPackId, m.getPackKey().get()));
} }
} }
@ -410,8 +387,8 @@ public final class IncomingMessageHandler {
} else { } else {
return false; return false;
} }
final var recipientId = recipientResolver.resolveRecipient(source); final var recipientId = context.getRecipientHelper().resolveRecipient(source);
if (contactHelper.isContactBlocked(recipientId)) { if (context.getContactHelper().isContactBlocked(recipientId)) {
return true; return true;
} }
@ -419,7 +396,7 @@ public final class IncomingMessageHandler {
var message = content.getDataMessage().get(); var message = content.getDataMessage().get();
if (message.getGroupContext().isPresent()) { if (message.getGroupContext().isPresent()) {
var groupId = GroupUtils.getGroupId(message.getGroupContext().get()); var groupId = GroupUtils.getGroupId(message.getGroupContext().get());
return groupHelper.isGroupBlocked(groupId); return context.getGroupHelper().isGroupBlocked(groupId);
} }
} }
@ -453,12 +430,12 @@ public final class IncomingMessageHandler {
} }
var groupId = GroupUtils.getGroupId(message.getGroupContext().get()); var groupId = GroupUtils.getGroupId(message.getGroupContext().get());
var group = groupHelper.getGroup(groupId); var group = context.getGroupHelper().getGroup(groupId);
if (group == null) { if (group == null) {
return false; return false;
} }
final var recipientId = recipientResolver.resolveRecipient(source); final var recipientId = context.getRecipientHelper().resolveRecipient(source);
if (!group.isMember(recipientId) && !(group.isPendingMember(recipientId) && message.isGroupV2Update())) { if (!group.isMember(recipientId) && !(group.isPendingMember(recipientId) && message.isGroupV2Update())) {
return true; return true;
} }
@ -487,7 +464,7 @@ public final class IncomingMessageHandler {
if (message.getGroupContext().get().getGroupV1().isPresent()) { if (message.getGroupContext().get().getGroupV1().isPresent()) {
var groupInfo = message.getGroupContext().get().getGroupV1().get(); var groupInfo = message.getGroupContext().get().getGroupV1().get();
var groupId = GroupId.v1(groupInfo.getGroupId()); var groupId = GroupId.v1(groupInfo.getGroupId());
var group = groupHelper.getGroup(groupId); var group = context.getGroupHelper().getGroup(groupId);
if (group == null || group instanceof GroupInfoV1) { if (group == null || group instanceof GroupInfoV1) {
var groupV1 = (GroupInfoV1) group; var groupV1 = (GroupInfoV1) group;
switch (groupInfo.getType()) { switch (groupInfo.getType()) {
@ -498,7 +475,7 @@ public final class IncomingMessageHandler {
if (groupInfo.getAvatar().isPresent()) { if (groupInfo.getAvatar().isPresent()) {
var avatar = groupInfo.getAvatar().get(); var avatar = groupInfo.getAvatar().get();
groupHelper.downloadGroupAvatar(groupV1.getGroupId(), avatar); context.getGroupHelper().downloadGroupAvatar(groupV1.getGroupId(), avatar);
} }
if (groupInfo.getName().isPresent()) { if (groupInfo.getName().isPresent()) {
@ -509,7 +486,7 @@ public final class IncomingMessageHandler {
groupV1.addMembers(groupInfo.getMembers() groupV1.addMembers(groupInfo.getMembers()
.get() .get()
.stream() .stream()
.map(recipientResolver::resolveRecipient) .map(context.getRecipientHelper()::resolveRecipient)
.collect(Collectors.toSet())); .collect(Collectors.toSet()));
} }
@ -542,9 +519,10 @@ public final class IncomingMessageHandler {
final var groupContext = message.getGroupContext().get().getGroupV2().get(); final var groupContext = message.getGroupContext().get().getGroupV2().get();
final var groupMasterKey = groupContext.getMasterKey(); final var groupMasterKey = groupContext.getMasterKey();
groupHelper.getOrMigrateGroup(groupMasterKey, context.getGroupHelper()
groupContext.getRevision(), .getOrMigrateGroup(groupMasterKey,
groupContext.hasSignedGroupChange() ? groupContext.getSignedGroupChange() : null); groupContext.getRevision(),
groupContext.hasSignedGroupChange() ? groupContext.getSignedGroupChange() : null);
} }
} }
@ -567,19 +545,20 @@ public final class IncomingMessageHandler {
// disappearing message timer already stored in the DecryptedGroup // disappearing message timer already stored in the DecryptedGroup
} }
} else if (conversationPartnerAddress != null) { } else if (conversationPartnerAddress != null) {
contactHelper.setExpirationTimer(conversationPartnerAddress, message.getExpiresInSeconds()); context.getContactHelper()
.setExpirationTimer(conversationPartnerAddress, message.getExpiresInSeconds());
} }
} }
if (!ignoreAttachments) { if (!ignoreAttachments) {
if (message.getAttachments().isPresent()) { if (message.getAttachments().isPresent()) {
for (var attachment : message.getAttachments().get()) { for (var attachment : message.getAttachments().get()) {
attachmentHelper.downloadAttachment(attachment); context.getAttachmentHelper().downloadAttachment(attachment);
} }
} }
if (message.getSharedContacts().isPresent()) { if (message.getSharedContacts().isPresent()) {
for (var contact : message.getSharedContacts().get()) { for (var contact : message.getSharedContacts().get()) {
if (contact.getAvatar().isPresent()) { if (contact.getAvatar().isPresent()) {
attachmentHelper.downloadAttachment(contact.getAvatar().get().getAttachment()); context.getAttachmentHelper().downloadAttachment(contact.getAvatar().get().getAttachment());
} }
} }
} }
@ -587,7 +566,7 @@ public final class IncomingMessageHandler {
final var previews = message.getPreviews().get(); final var previews = message.getPreviews().get();
for (var preview : previews) { for (var preview : previews) {
if (preview.getImage().isPresent()) { if (preview.getImage().isPresent()) {
attachmentHelper.downloadAttachment(preview.getImage().get()); context.getAttachmentHelper().downloadAttachment(preview.getImage().get());
} }
} }
} }
@ -597,7 +576,7 @@ public final class IncomingMessageHandler {
for (var quotedAttachment : quote.getAttachments()) { for (var quotedAttachment : quote.getAttachments()) {
final var thumbnail = quotedAttachment.getThumbnail(); final var thumbnail = quotedAttachment.getThumbnail();
if (thumbnail != null) { if (thumbnail != null) {
attachmentHelper.downloadAttachment(thumbnail); context.getAttachmentHelper().downloadAttachment(thumbnail);
} }
} }
} }
@ -622,7 +601,7 @@ public final class IncomingMessageHandler {
sticker = new Sticker(stickerPackId, messageSticker.getPackKey()); sticker = new Sticker(stickerPackId, messageSticker.getPackKey());
account.getStickerStore().updateSticker(sticker); account.getStickerStore().updateSticker(sticker);
} }
jobExecutor.enqueueJob(new RetrieveStickerPackJob(stickerPackId, messageSticker.getPackKey())); context.getJobExecutor().enqueueJob(new RetrieveStickerPackJob(stickerPackId, messageSticker.getPackKey()));
} }
return actions; return actions;
} }

View file

@ -1,6 +1,5 @@
package org.asamk.signal.manager.helper; package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.AvatarStore;
import org.asamk.signal.manager.SignalDependencies; import org.asamk.signal.manager.SignalDependencies;
import org.asamk.signal.manager.config.ServiceConfig; import org.asamk.signal.manager.config.ServiceConfig;
import org.asamk.signal.manager.storage.SignalAccount; import org.asamk.signal.manager.storage.SignalAccount;
@ -43,22 +42,12 @@ public final class ProfileHelper {
private final SignalAccount account; private final SignalAccount account;
private final SignalDependencies dependencies; private final SignalDependencies dependencies;
private final AvatarStore avatarStore; private final Context context;
private final UnidentifiedAccessProvider unidentifiedAccessProvider;
private final SignalServiceAddressResolver addressResolver;
public ProfileHelper( public ProfileHelper(final Context context) {
final SignalAccount account, this.account = context.getAccount();
final SignalDependencies dependencies, this.dependencies = context.getDependencies();
final AvatarStore avatarStore, this.context = context;
final UnidentifiedAccessProvider unidentifiedAccessProvider,
final SignalServiceAddressResolver addressResolver
) {
this.account = account;
this.dependencies = dependencies;
this.avatarStore = avatarStore;
this.unidentifiedAccessProvider = unidentifiedAccessProvider;
this.addressResolver = addressResolver;
} }
public Profile getRecipientProfile(RecipientId recipientId) { public Profile getRecipientProfile(RecipientId recipientId) {
@ -139,7 +128,8 @@ public final class ProfileHelper {
if (uploadProfile) { if (uploadProfile) {
try (final var streamDetails = avatar == null try (final var streamDetails = avatar == null
? avatarStore.retrieveProfileAvatar(account.getSelfAddress()) ? context.getAvatarStore()
.retrieveProfileAvatar(account.getSelfAddress())
: avatar.isPresent() ? Utils.createStreamDetailsFromFile(avatar.get()) : null) { : avatar.isPresent() ? Utils.createStreamDetailsFromFile(avatar.get()) : null) {
final var avatarPath = dependencies.getAccountManager() final var avatarPath = dependencies.getAccountManager()
.setVersionedProfile(account.getAci(), .setVersionedProfile(account.getAci(),
@ -157,10 +147,11 @@ public final class ProfileHelper {
if (avatar != null) { if (avatar != null) {
if (avatar.isPresent()) { if (avatar.isPresent()) {
avatarStore.storeProfileAvatar(account.getSelfAddress(), context.getAvatarStore()
outputStream -> IOUtils.copyFileToStream(avatar.get(), outputStream)); .storeProfileAvatar(account.getSelfAddress(),
outputStream -> IOUtils.copyFileToStream(avatar.get(), outputStream));
} else { } else {
avatarStore.deleteProfileAvatar(account.getSelfAddress()); context.getAvatarStore().deleteProfileAvatar(account.getSelfAddress());
} }
} }
account.getProfileStore().storeProfile(account.getSelfRecipientId(), newProfile); account.getProfileStore().storeProfile(account.getSelfRecipientId(), newProfile);
@ -224,7 +215,9 @@ public final class ProfileHelper {
) { ) {
var profile = account.getProfileStore().getProfile(recipientId); var profile = account.getProfileStore().getProfile(recipientId);
if (profile == null || !Objects.equals(avatarPath, profile.getAvatarUrlPath())) { if (profile == null || !Objects.equals(avatarPath, profile.getAvatarUrlPath())) {
downloadProfileAvatar(addressResolver.resolveSignalServiceAddress(recipientId), avatarPath, profileKey); downloadProfileAvatar(context.getRecipientHelper().resolveSignalServiceAddress(recipientId),
avatarPath,
profileKey);
var builder = profile == null ? Profile.newBuilder() : Profile.newBuilder(profile); var builder = profile == null ? Profile.newBuilder() : Profile.newBuilder(profile);
account.getProfileStore().storeProfile(recipientId, builder.withAvatarUrlPath(avatarPath).build()); account.getProfileStore().storeProfile(recipientId, builder.withAvatarUrlPath(avatarPath).build());
} }
@ -250,7 +243,7 @@ public final class ProfileHelper {
var unidentifiedAccess = getUnidentifiedAccess(recipientId); var unidentifiedAccess = getUnidentifiedAccess(recipientId);
var profileKey = Optional.fromNullable(account.getProfileStore().getProfileKey(recipientId)); var profileKey = Optional.fromNullable(account.getProfileStore().getProfileKey(recipientId));
final var address = addressResolver.resolveSignalServiceAddress(recipientId); final var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId);
return retrieveProfile(address, profileKey, unidentifiedAccess, requestType).doOnSuccess(p -> { return retrieveProfile(address, profileKey, unidentifiedAccess, requestType).doOnSuccess(p -> {
final var encryptedProfile = p.getProfile(); final var encryptedProfile = p.getProfile();
@ -289,7 +282,7 @@ public final class ProfileHelper {
} }
} catch (InvalidKeyException ignored) { } catch (InvalidKeyException ignored) {
logger.warn("Got invalid identity key in profile for {}", logger.warn("Got invalid identity key in profile for {}",
addressResolver.resolveSignalServiceAddress(recipientId).getIdentifier()); context.getRecipientHelper().resolveSignalServiceAddress(recipientId).getIdentifier());
} }
}).doOnError(e -> { }).doOnError(e -> {
logger.warn("Failed to retrieve profile, ignoring: {}", e.getMessage()); logger.warn("Failed to retrieve profile, ignoring: {}", e.getMessage());
@ -333,7 +326,7 @@ public final class ProfileHelper {
) { ) {
if (avatarPath == null) { if (avatarPath == null) {
try { try {
avatarStore.deleteProfileAvatar(address); context.getAvatarStore().deleteProfileAvatar(address);
} catch (IOException e) { } catch (IOException e) {
logger.warn("Failed to delete local profile avatar, ignoring: {}", e.getMessage()); logger.warn("Failed to delete local profile avatar, ignoring: {}", e.getMessage());
} }
@ -341,8 +334,9 @@ public final class ProfileHelper {
} }
try { try {
avatarStore.storeProfileAvatar(address, context.getAvatarStore()
outputStream -> retrieveProfileAvatar(avatarPath, profileKey, outputStream)); .storeProfileAvatar(address,
outputStream -> retrieveProfileAvatar(avatarPath, profileKey, outputStream));
} catch (Throwable e) { } catch (Throwable e) {
if (e instanceof AssertionError && e.getCause() instanceof InterruptedException) { if (e instanceof AssertionError && e.getCause() instanceof InterruptedException) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
@ -374,7 +368,7 @@ public final class ProfileHelper {
} }
private Optional<UnidentifiedAccess> getUnidentifiedAccess(RecipientId recipientId) { private Optional<UnidentifiedAccess> getUnidentifiedAccess(RecipientId recipientId) {
var unidentifiedAccess = unidentifiedAccessProvider.getAccessFor(recipientId, true); var unidentifiedAccess = context.getUnidentifiedAccessHelper().getAccessFor(recipientId, true);
if (unidentifiedAccess.isPresent()) { if (unidentifiedAccess.isPresent()) {
return unidentifiedAccess.get().getTargetUnidentifiedAccess(); return unidentifiedAccess.get().getTargetUnidentifiedAccess();

View file

@ -1,9 +0,0 @@
package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.storage.recipients.RecipientId;
import org.signal.zkgroup.profiles.ProfileKeyCredential;
public interface ProfileKeyCredentialProvider {
ProfileKeyCredential getProfileKeyCredential(RecipientId recipientId);
}

View file

@ -1,9 +0,0 @@
package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.storage.recipients.Profile;
import org.asamk.signal.manager.storage.recipients.RecipientId;
public interface ProfileProvider {
Profile getProfile(RecipientId recipientId);
}

View file

@ -32,14 +32,10 @@ public class RecipientHelper {
private final SignalDependencies dependencies; private final SignalDependencies dependencies;
private final ServiceEnvironmentConfig serviceEnvironmentConfig; private final ServiceEnvironmentConfig serviceEnvironmentConfig;
public RecipientHelper( public RecipientHelper(final Context context) {
final SignalAccount account, this.account = context.getAccount();
final SignalDependencies dependencies, this.dependencies = context.getDependencies();
final ServiceEnvironmentConfig serviceEnvironmentConfig this.serviceEnvironmentConfig = dependencies.getServiceEnvironmentConfig();
) {
this.account = account;
this.dependencies = dependencies;
this.serviceEnvironmentConfig = serviceEnvironmentConfig;
} }
public SignalServiceAddress resolveSignalServiceAddress(RecipientId recipientId) { public SignalServiceAddress resolveSignalServiceAddress(RecipientId recipientId) {
@ -64,6 +60,10 @@ public class RecipientHelper {
.toSignalServiceAddress(); .toSignalServiceAddress();
} }
public RecipientId resolveRecipient(final SignalServiceAddress address) {
return account.getRecipientStore().resolveRecipient(address);
}
public Set<RecipientId> resolveRecipients(Collection<RecipientIdentifier.Single> recipients) throws IOException, UnregisteredRecipientException { public Set<RecipientId> resolveRecipients(Collection<RecipientIdentifier.Single> recipients) throws IOException, UnregisteredRecipientException {
final var recipientIds = new HashSet<RecipientId>(recipients.size()); final var recipientIds = new HashSet<RecipientId>(recipients.size());
for (var number : recipients) { for (var number : recipients) {

View file

@ -1,11 +0,0 @@
package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.api.UnregisteredRecipientException;
import org.asamk.signal.manager.storage.recipients.RecipientId;
import java.io.IOException;
public interface RecipientRegistrationRefresher {
RecipientId refreshRecipientRegistration(RecipientId recipientId) throws IOException, UnregisteredRecipientException;
}

View file

@ -1,8 +0,0 @@
package org.asamk.signal.manager.helper;
import org.signal.zkgroup.profiles.ProfileKey;
public interface SelfProfileKeyProvider {
ProfileKey getProfileKey();
}

View file

@ -1,8 +0,0 @@
package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.storage.recipients.RecipientId;
public interface SelfRecipientIdProvider {
RecipientId getSelfRecipientId();
}

View file

@ -11,7 +11,6 @@ import org.asamk.signal.manager.storage.SignalAccount;
import org.asamk.signal.manager.storage.groups.GroupInfo; import org.asamk.signal.manager.storage.groups.GroupInfo;
import org.asamk.signal.manager.storage.recipients.Profile; import org.asamk.signal.manager.storage.recipients.Profile;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
import org.asamk.signal.manager.storage.recipients.RecipientResolver;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.whispersystems.libsignal.InvalidKeyException; import org.whispersystems.libsignal.InvalidKeyException;
@ -53,34 +52,12 @@ public class SendHelper {
private final SignalAccount account; private final SignalAccount account;
private final SignalDependencies dependencies; private final SignalDependencies dependencies;
private final UnidentifiedAccessHelper unidentifiedAccessHelper; private final Context context;
private final SignalServiceAddressResolver addressResolver;
private final RecipientResolver recipientResolver;
private final IdentityFailureHandler identityFailureHandler;
private final GroupProvider groupProvider;
private final ProfileHelper profileHelper;
private final RecipientRegistrationRefresher recipientRegistrationRefresher;
public SendHelper( public SendHelper(final Context context) {
final SignalAccount account, this.account = context.getAccount();
final SignalDependencies dependencies, this.dependencies = context.getDependencies();
final UnidentifiedAccessHelper unidentifiedAccessHelper, this.context = context;
final SignalServiceAddressResolver addressResolver,
final RecipientResolver recipientResolver,
final IdentityFailureHandler identityFailureHandler,
final GroupProvider groupProvider,
final ProfileHelper profileHelper,
final RecipientRegistrationRefresher recipientRegistrationRefresher
) {
this.account = account;
this.dependencies = dependencies;
this.unidentifiedAccessHelper = unidentifiedAccessHelper;
this.addressResolver = addressResolver;
this.recipientResolver = recipientResolver;
this.identityFailureHandler = identityFailureHandler;
this.groupProvider = groupProvider;
this.profileHelper = profileHelper;
this.recipientRegistrationRefresher = recipientRegistrationRefresher;
} }
/** /**
@ -223,22 +200,22 @@ public class SendHelper {
public SendMessageResult sendSyncMessage(SignalServiceSyncMessage message) { public SendMessageResult sendSyncMessage(SignalServiceSyncMessage message) {
var messageSender = dependencies.getMessageSender(); var messageSender = dependencies.getMessageSender();
try { try {
return messageSender.sendSyncMessage(message, unidentifiedAccessHelper.getAccessForSync()); return messageSender.sendSyncMessage(message, context.getUnidentifiedAccessHelper().getAccessForSync());
} catch (UnregisteredUserException e) { } catch (UnregisteredUserException e) {
var address = addressResolver.resolveSignalServiceAddress(account.getSelfRecipientId()); var address = context.getRecipientHelper().resolveSignalServiceAddress(account.getSelfRecipientId());
return SendMessageResult.unregisteredFailure(address); return SendMessageResult.unregisteredFailure(address);
} catch (ProofRequiredException e) { } catch (ProofRequiredException e) {
var address = addressResolver.resolveSignalServiceAddress(account.getSelfRecipientId()); var address = context.getRecipientHelper().resolveSignalServiceAddress(account.getSelfRecipientId());
return SendMessageResult.proofRequiredFailure(address, e); return SendMessageResult.proofRequiredFailure(address, e);
} catch (RateLimitException e) { } catch (RateLimitException e) {
var address = addressResolver.resolveSignalServiceAddress(account.getSelfRecipientId()); var address = context.getRecipientHelper().resolveSignalServiceAddress(account.getSelfRecipientId());
logger.warn("Sending failed due to rate limiting from the signal server: {}", e.getMessage()); logger.warn("Sending failed due to rate limiting from the signal server: {}", e.getMessage());
return SendMessageResult.networkFailure(address); return SendMessageResult.networkFailure(address);
} catch (org.whispersystems.signalservice.api.crypto.UntrustedIdentityException e) { } catch (org.whispersystems.signalservice.api.crypto.UntrustedIdentityException e) {
var address = addressResolver.resolveSignalServiceAddress(account.getSelfRecipientId()); var address = context.getRecipientHelper().resolveSignalServiceAddress(account.getSelfRecipientId());
return SendMessageResult.identityFailure(address, e.getIdentityKey()); return SendMessageResult.identityFailure(address, e.getIdentityKey());
} catch (IOException e) { } catch (IOException e) {
var address = addressResolver.resolveSignalServiceAddress(account.getSelfRecipientId()); var address = context.getRecipientHelper().resolveSignalServiceAddress(account.getSelfRecipientId());
logger.warn("Failed to send message due to IO exception: {}", e.getMessage()); logger.warn("Failed to send message due to IO exception: {}", e.getMessage());
return SendMessageResult.networkFailure(address); return SendMessageResult.networkFailure(address);
} }
@ -292,7 +269,7 @@ public class SendHelper {
} }
private GroupInfo getGroupForSending(GroupId groupId) throws GroupNotFoundException, NotAGroupMemberException { private GroupInfo getGroupForSending(GroupId groupId) throws GroupNotFoundException, NotAGroupMemberException {
var g = groupProvider.getGroup(groupId); var g = context.getGroupHelper().getGroup(groupId);
if (g == null) { if (g == null) {
throw new GroupNotFoundException(groupId); throw new GroupNotFoundException(groupId);
} }
@ -327,7 +304,7 @@ public class SendHelper {
results.stream().filter(SendMessageResult::isSuccess).forEach(allResults::add); results.stream().filter(SendMessageResult::isSuccess).forEach(allResults::add);
final var failedTargets = results.stream() final var failedTargets = results.stream()
.filter(r -> !r.isSuccess()) .filter(r -> !r.isSuccess())
.map(r -> recipientResolver.resolveRecipient(r.getAddress())) .map(r -> context.getRecipientHelper().resolveRecipient(r.getAddress()))
.toList(); .toList();
if (failedTargets.size() > 0) { if (failedTargets.size() > 0) {
senderKeyTargets = new HashSet<>(senderKeyTargets); senderKeyTargets = new HashSet<>(senderKeyTargets);
@ -357,7 +334,7 @@ public class SendHelper {
} }
private Set<RecipientId> getSenderKeyCapableRecipientIds(final Set<RecipientId> recipientIds) { private Set<RecipientId> getSenderKeyCapableRecipientIds(final Set<RecipientId> recipientIds) {
final var selfProfile = profileHelper.getRecipientProfile(account.getSelfRecipientId()); final var selfProfile = context.getProfileHelper().getRecipientProfile(account.getSelfRecipientId());
if (selfProfile == null || !selfProfile.getCapabilities().contains(Profile.Capability.senderKey)) { if (selfProfile == null || !selfProfile.getCapabilities().contains(Profile.Capability.senderKey)) {
logger.debug("Not all of our devices support sender key. Using legacy."); logger.debug("Not all of our devices support sender key. Using legacy.");
return Set.of(); return Set.of();
@ -365,14 +342,14 @@ public class SendHelper {
final var senderKeyTargets = new HashSet<RecipientId>(); final var senderKeyTargets = new HashSet<RecipientId>();
final var recipientList = new ArrayList<>(recipientIds); final var recipientList = new ArrayList<>(recipientIds);
final var profiles = profileHelper.getRecipientProfile(recipientList).iterator(); final var profiles = context.getProfileHelper().getRecipientProfile(recipientList).iterator();
for (final var recipientId : recipientList) { for (final var recipientId : recipientList) {
final var profile = profiles.next(); final var profile = profiles.next();
if (profile == null || !profile.getCapabilities().contains(Profile.Capability.senderKey)) { if (profile == null || !profile.getCapabilities().contains(Profile.Capability.senderKey)) {
continue; continue;
} }
final var access = unidentifiedAccessHelper.getAccessFor(recipientId); final var access = context.getUnidentifiedAccessHelper().getAccessFor(recipientId);
if (!access.isPresent() || !access.get().getTargetUnidentifiedAccess().isPresent()) { if (!access.isPresent() || !access.get().getTargetUnidentifiedAccess().isPresent()) {
continue; continue;
} }
@ -398,8 +375,10 @@ public class SendHelper {
final LegacySenderHandler sender, final Set<RecipientId> recipientIds, final boolean isRecipientUpdate final LegacySenderHandler sender, final Set<RecipientId> recipientIds, final boolean isRecipientUpdate
) throws IOException { ) throws IOException {
final var recipientIdList = new ArrayList<>(recipientIds); final var recipientIdList = new ArrayList<>(recipientIds);
final var addresses = recipientIdList.stream().map(addressResolver::resolveSignalServiceAddress).toList(); final var addresses = recipientIdList.stream()
final var unidentifiedAccesses = unidentifiedAccessHelper.getAccessFor(recipientIdList); .map(context.getRecipientHelper()::resolveSignalServiceAddress)
.toList();
final var unidentifiedAccesses = context.getUnidentifiedAccessHelper().getAccessFor(recipientIdList);
try { try {
final var results = sender.send(addresses, unidentifiedAccesses, isRecipientUpdate); final var results = sender.send(addresses, unidentifiedAccesses, isRecipientUpdate);
@ -433,9 +412,10 @@ public class SendHelper {
} }
List<SignalServiceAddress> addresses = recipientIdList.stream() List<SignalServiceAddress> addresses = recipientIdList.stream()
.map(addressResolver::resolveSignalServiceAddress) .map(context.getRecipientHelper()::resolveSignalServiceAddress)
.collect(Collectors.toList()); .collect(Collectors.toList());
List<UnidentifiedAccess> unidentifiedAccesses = unidentifiedAccessHelper.getAccessFor(recipientIdList) List<UnidentifiedAccess> unidentifiedAccesses = context.getUnidentifiedAccessHelper()
.getAccessFor(recipientIdList)
.stream() .stream()
.map(Optional::get) .map(Optional::get)
.map(UnidentifiedAccessPair::getTargetUnidentifiedAccess) .map(UnidentifiedAccessPair::getTargetUnidentifiedAccess)
@ -490,19 +470,21 @@ public class SendHelper {
private SendMessageResult handleSendMessage(RecipientId recipientId, SenderHandler s) { private SendMessageResult handleSendMessage(RecipientId recipientId, SenderHandler s) {
var messageSender = dependencies.getMessageSender(); var messageSender = dependencies.getMessageSender();
var address = addressResolver.resolveSignalServiceAddress(recipientId); var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId);
try { try {
try { try {
return s.send(messageSender, address, unidentifiedAccessHelper.getAccessFor(recipientId)); return s.send(messageSender, address, context.getUnidentifiedAccessHelper().getAccessFor(recipientId));
} catch (UnregisteredUserException e) { } catch (UnregisteredUserException e) {
final RecipientId newRecipientId; final RecipientId newRecipientId;
try { try {
newRecipientId = recipientRegistrationRefresher.refreshRecipientRegistration(recipientId); newRecipientId = context.getRecipientHelper().refreshRegisteredUser(recipientId);
} catch (UnregisteredRecipientException ex) { } catch (UnregisteredRecipientException ex) {
return SendMessageResult.unregisteredFailure(address); return SendMessageResult.unregisteredFailure(address);
} }
address = addressResolver.resolveSignalServiceAddress(newRecipientId); address = context.getRecipientHelper().resolveSignalServiceAddress(newRecipientId);
return s.send(messageSender, address, unidentifiedAccessHelper.getAccessFor(newRecipientId)); return s.send(messageSender,
address,
context.getUnidentifiedAccessHelper().getAccessFor(newRecipientId));
} }
} catch (UnregisteredUserException e) { } catch (UnregisteredUserException e) {
return SendMessageResult.unregisteredFailure(address); return SendMessageResult.unregisteredFailure(address);
@ -534,7 +516,7 @@ public class SendHelper {
private void handleSendMessageResult(final SendMessageResult r) { private void handleSendMessageResult(final SendMessageResult r) {
if (r.isSuccess() && !r.getSuccess().isUnidentified()) { if (r.isSuccess() && !r.getSuccess().isUnidentified()) {
final var recipientId = recipientResolver.resolveRecipient(r.getAddress()); final var recipientId = context.getRecipientHelper().resolveRecipient(r.getAddress());
final var profile = account.getRecipientStore().getProfile(recipientId); final var profile = account.getRecipientStore().getProfile(recipientId);
if (profile != null && ( if (profile != null && (
profile.getUnidentifiedAccessMode() == Profile.UnidentifiedAccessMode.ENABLED profile.getUnidentifiedAccessMode() == Profile.UnidentifiedAccessMode.ENABLED
@ -548,7 +530,7 @@ public class SendHelper {
} }
} }
if (r.isUnregisteredFailure()) { if (r.isUnregisteredFailure()) {
final var recipientId = recipientResolver.resolveRecipient(r.getAddress()); final var recipientId = context.getRecipientHelper().resolveRecipient(r.getAddress());
final var profile = account.getRecipientStore().getProfile(recipientId); final var profile = account.getRecipientStore().getProfile(recipientId);
if (profile != null && ( if (profile != null && (
profile.getUnidentifiedAccessMode() == Profile.UnidentifiedAccessMode.ENABLED profile.getUnidentifiedAccessMode() == Profile.UnidentifiedAccessMode.ENABLED
@ -562,8 +544,8 @@ public class SendHelper {
} }
} }
if (r.getIdentityFailure() != null) { if (r.getIdentityFailure() != null) {
final var recipientId = recipientResolver.resolveRecipient(r.getAddress()); final var recipientId = context.getRecipientHelper().resolveRecipient(r.getAddress());
identityFailureHandler.handleIdentityFailure(recipientId, r.getIdentityFailure()); context.getIdentityHelper().handleIdentityFailure(recipientId, r.getIdentityFailure());
} }
} }

View file

@ -1,9 +0,0 @@
package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.storage.recipients.RecipientId;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
public interface SignalServiceAddressResolver {
SignalServiceAddress resolveSignalServiceAddress(RecipientId recipientId);
}

View file

@ -32,19 +32,12 @@ public class StorageHelper {
private final SignalAccount account; private final SignalAccount account;
private final SignalDependencies dependencies; private final SignalDependencies dependencies;
private final GroupHelper groupHelper; private final Context context;
private final ProfileHelper profileHelper;
public StorageHelper( public StorageHelper(final Context context) {
final SignalAccount account, this.account = context.getAccount();
final SignalDependencies dependencies, this.dependencies = context.getDependencies();
final GroupHelper groupHelper, this.context = context;
final ProfileHelper profileHelper
) {
this.account = account;
this.dependencies = dependencies;
this.groupHelper = groupHelper;
this.profileHelper = profileHelper;
} }
public void readDataFromStorage() throws IOException { public void readDataFromStorage() throws IOException {
@ -139,7 +132,7 @@ public class StorageHelper {
final var group = account.getGroupStore().getGroup(groupIdV1); final var group = account.getGroupStore().getGroup(groupIdV1);
if (group == null) { if (group == null) {
try { try {
groupHelper.sendGroupInfoRequest(groupIdV1, account.getSelfRecipientId()); context.getGroupHelper().sendGroupInfoRequest(groupIdV1, account.getSelfRecipientId());
} catch (Throwable e) { } catch (Throwable e) {
logger.warn("Failed to send group request", e); logger.warn("Failed to send group request", e);
} }
@ -169,7 +162,7 @@ public class StorageHelper {
return; return;
} }
final var group = groupHelper.getOrMigrateGroup(groupMasterKey, 0, null); final var group = context.getGroupHelper().getOrMigrateGroup(groupMasterKey, 0, null);
if (group.isBlocked() != groupV2Record.isBlocked()) { if (group.isBlocked() != groupV2Record.isBlocked()) {
group.setBlocked(groupV2Record.isBlocked()); group.setBlocked(groupV2Record.isBlocked());
account.getGroupStore().updateGroup(group); account.getGroupStore().updateGroup(group);
@ -225,16 +218,17 @@ public class StorageHelper {
if (profileKey != null) { if (profileKey != null) {
account.setProfileKey(profileKey); account.setProfileKey(profileKey);
final var avatarPath = accountRecord.getAvatarUrlPath().orNull(); final var avatarPath = accountRecord.getAvatarUrlPath().orNull();
profileHelper.downloadProfileAvatar(account.getSelfRecipientId(), avatarPath, profileKey); context.getProfileHelper().downloadProfileAvatar(account.getSelfRecipientId(), avatarPath, profileKey);
} }
} }
profileHelper.setProfile(false, context.getProfileHelper()
accountRecord.getGivenName().orNull(), .setProfile(false,
accountRecord.getFamilyName().orNull(), accountRecord.getGivenName().orNull(),
null, accountRecord.getFamilyName().orNull(),
null, null,
null); null,
null);
} }
private SignalStorageRecord getSignalStorageRecord(final StorageId accountId) throws IOException { private SignalStorageRecord getSignalStorageRecord(final StorageId accountId) throws IOException {

View file

@ -1,6 +1,5 @@
package org.asamk.signal.manager.helper; package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.AvatarStore;
import org.asamk.signal.manager.TrustLevel; import org.asamk.signal.manager.TrustLevel;
import org.asamk.signal.manager.storage.SignalAccount; import org.asamk.signal.manager.storage.SignalAccount;
import org.asamk.signal.manager.storage.groups.GroupInfoV1; import org.asamk.signal.manager.storage.groups.GroupInfoV1;
@ -40,30 +39,15 @@ public class SyncHelper {
private final static Logger logger = LoggerFactory.getLogger(SyncHelper.class); private final static Logger logger = LoggerFactory.getLogger(SyncHelper.class);
private final Context context;
private final SignalAccount account; private final SignalAccount account;
private final AttachmentHelper attachmentHelper;
private final SendHelper sendHelper;
private final GroupHelper groupHelper;
private final AvatarStore avatarStore;
private final SignalServiceAddressResolver addressResolver;
public SyncHelper( public SyncHelper(final Context context) {
final SignalAccount account, this.context = context;
final AttachmentHelper attachmentHelper, this.account = context.getAccount();
final SendHelper sendHelper,
final GroupHelper groupHelper,
final AvatarStore avatarStore,
final SignalServiceAddressResolver addressResolver
) {
this.account = account;
this.attachmentHelper = attachmentHelper;
this.sendHelper = sendHelper;
this.groupHelper = groupHelper;
this.avatarStore = avatarStore;
this.addressResolver = addressResolver;
} }
public void requestAllSyncData() throws IOException { public void requestAllSyncData() {
requestSyncGroups(); requestSyncGroups();
requestSyncContacts(); requestSyncContacts();
requestSyncBlocked(); requestSyncBlocked();
@ -71,8 +55,9 @@ public class SyncHelper {
requestSyncKeys(); requestSyncKeys();
} }
public void sendSyncFetchProfileMessage() throws IOException { public void sendSyncFetchProfileMessage() {
sendHelper.sendSyncMessage(SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.LOCAL_PROFILE)); context.getSendHelper()
.sendSyncMessage(SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.LOCAL_PROFILE));
} }
public void sendGroups() throws IOException { public void sendGroups() throws IOException {
@ -87,9 +72,9 @@ public class SyncHelper {
Optional.fromNullable(groupInfo.name), Optional.fromNullable(groupInfo.name),
groupInfo.getMembers() groupInfo.getMembers()
.stream() .stream()
.map(addressResolver::resolveSignalServiceAddress) .map(context.getRecipientHelper()::resolveSignalServiceAddress)
.toList(), .toList(),
groupHelper.createGroupAvatarAttachment(groupInfo.getGroupId()), context.getGroupHelper().createGroupAvatarAttachment(groupInfo.getGroupId()),
groupInfo.isMember(account.getSelfRecipientId()), groupInfo.isMember(account.getSelfRecipientId()),
Optional.of(groupInfo.messageExpirationTime), Optional.of(groupInfo.messageExpirationTime),
Optional.fromNullable(groupInfo.color), Optional.fromNullable(groupInfo.color),
@ -108,7 +93,7 @@ public class SyncHelper {
.withLength(groupsFile.length()) .withLength(groupsFile.length())
.build(); .build();
sendHelper.sendSyncMessage(SignalServiceSyncMessage.forGroups(attachmentStream)); context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forGroups(attachmentStream));
} }
} }
} finally { } finally {
@ -129,7 +114,7 @@ public class SyncHelper {
for (var contactPair : account.getContactStore().getContacts()) { for (var contactPair : account.getContactStore().getContacts()) {
final var recipientId = contactPair.first(); final var recipientId = contactPair.first();
final var contact = contactPair.second(); final var contact = contactPair.second();
final var address = addressResolver.resolveSignalServiceAddress(recipientId); final var address = context.getRecipientHelper().resolveSignalServiceAddress(recipientId);
var currentIdentity = account.getIdentityKeyStore().getIdentity(recipientId); var currentIdentity = account.getIdentityKeyStore().getIdentity(recipientId);
VerifiedMessage verifiedMessage = null; VerifiedMessage verifiedMessage = null;
@ -176,8 +161,9 @@ public class SyncHelper {
.withLength(contactsFile.length()) .withLength(contactsFile.length())
.build(); .build();
sendHelper.sendSyncMessage(SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream, context.getSendHelper()
true))); .sendSyncMessage(SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream,
true)));
} }
} }
} finally { } finally {
@ -189,11 +175,11 @@ public class SyncHelper {
} }
} }
public void sendBlockedList() throws IOException { public void sendBlockedList() {
var addresses = new ArrayList<SignalServiceAddress>(); var addresses = new ArrayList<SignalServiceAddress>();
for (var record : account.getContactStore().getContacts()) { for (var record : account.getContactStore().getContacts()) {
if (record.second().isBlocked()) { if (record.second().isBlocked()) {
addresses.add(addressResolver.resolveSignalServiceAddress(record.first())); addresses.add(context.getRecipientHelper().resolveSignalServiceAddress(record.first()));
} }
} }
var groupIds = new ArrayList<byte[]>(); var groupIds = new ArrayList<byte[]>();
@ -202,7 +188,8 @@ public class SyncHelper {
groupIds.add(record.getGroupId().serialize()); groupIds.add(record.getGroupId().serialize());
} }
} }
sendHelper.sendSyncMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(addresses, groupIds))); context.getSendHelper()
.sendSyncMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(addresses, groupIds)));
} }
public void sendVerifiedMessage( public void sendVerifiedMessage(
@ -212,21 +199,21 @@ public class SyncHelper {
identityKey, identityKey,
trustLevel.toVerifiedState(), trustLevel.toVerifiedState(),
System.currentTimeMillis()); System.currentTimeMillis());
sendHelper.sendSyncMessage(SignalServiceSyncMessage.forVerified(verifiedMessage)); context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forVerified(verifiedMessage));
} }
public void sendKeysMessage() throws IOException { public void sendKeysMessage() {
var keysMessage = new KeysMessage(Optional.fromNullable(account.getStorageKey())); var keysMessage = new KeysMessage(Optional.fromNullable(account.getStorageKey()));
sendHelper.sendSyncMessage(SignalServiceSyncMessage.forKeys(keysMessage)); context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forKeys(keysMessage));
} }
public void sendConfigurationMessage() throws IOException { public void sendConfigurationMessage() {
final var config = account.getConfigurationStore(); final var config = account.getConfigurationStore();
var configurationMessage = new ConfigurationMessage(Optional.fromNullable(config.getReadReceipts()), var configurationMessage = new ConfigurationMessage(Optional.fromNullable(config.getReadReceipts()),
Optional.fromNullable(config.getUnidentifiedDeliveryIndicators()), Optional.fromNullable(config.getUnidentifiedDeliveryIndicators()),
Optional.fromNullable(config.getTypingIndicators()), Optional.fromNullable(config.getTypingIndicators()),
Optional.fromNullable(config.getLinkPreviews())); Optional.fromNullable(config.getLinkPreviews()));
sendHelper.sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage)); context.getSendHelper().sendSyncMessage(SignalServiceSyncMessage.forConfiguration(configurationMessage));
} }
public void handleSyncDeviceContacts(final InputStream input) throws IOException { public void handleSyncDeviceContacts(final InputStream input) throws IOException {
@ -282,48 +269,48 @@ public class SyncHelper {
} }
} }
private void requestSyncGroups() throws IOException { private void requestSyncGroups() {
var r = SignalServiceProtos.SyncMessage.Request.newBuilder() var r = SignalServiceProtos.SyncMessage.Request.newBuilder()
.setType(SignalServiceProtos.SyncMessage.Request.Type.GROUPS) .setType(SignalServiceProtos.SyncMessage.Request.Type.GROUPS)
.build(); .build();
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
sendHelper.sendSyncMessage(message); context.getSendHelper().sendSyncMessage(message);
} }
private void requestSyncContacts() throws IOException { private void requestSyncContacts() {
var r = SignalServiceProtos.SyncMessage.Request.newBuilder() var r = SignalServiceProtos.SyncMessage.Request.newBuilder()
.setType(SignalServiceProtos.SyncMessage.Request.Type.CONTACTS) .setType(SignalServiceProtos.SyncMessage.Request.Type.CONTACTS)
.build(); .build();
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
sendHelper.sendSyncMessage(message); context.getSendHelper().sendSyncMessage(message);
} }
private void requestSyncBlocked() throws IOException { private void requestSyncBlocked() {
var r = SignalServiceProtos.SyncMessage.Request.newBuilder() var r = SignalServiceProtos.SyncMessage.Request.newBuilder()
.setType(SignalServiceProtos.SyncMessage.Request.Type.BLOCKED) .setType(SignalServiceProtos.SyncMessage.Request.Type.BLOCKED)
.build(); .build();
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
sendHelper.sendSyncMessage(message); context.getSendHelper().sendSyncMessage(message);
} }
private void requestSyncConfiguration() throws IOException { private void requestSyncConfiguration() {
var r = SignalServiceProtos.SyncMessage.Request.newBuilder() var r = SignalServiceProtos.SyncMessage.Request.newBuilder()
.setType(SignalServiceProtos.SyncMessage.Request.Type.CONFIGURATION) .setType(SignalServiceProtos.SyncMessage.Request.Type.CONFIGURATION)
.build(); .build();
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
sendHelper.sendSyncMessage(message); context.getSendHelper().sendSyncMessage(message);
} }
private void requestSyncKeys() throws IOException { private void requestSyncKeys() {
var r = SignalServiceProtos.SyncMessage.Request.newBuilder() var r = SignalServiceProtos.SyncMessage.Request.newBuilder()
.setType(SignalServiceProtos.SyncMessage.Request.Type.KEYS) .setType(SignalServiceProtos.SyncMessage.Request.Type.KEYS)
.build(); .build();
var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r)); var message = SignalServiceSyncMessage.forRequest(new RequestMessage(r));
sendHelper.sendSyncMessage(message); context.getSendHelper().sendSyncMessage(message);
} }
private Optional<SignalServiceAttachmentStream> createContactAvatarAttachment(SignalServiceAddress address) throws IOException { private Optional<SignalServiceAttachmentStream> createContactAvatarAttachment(SignalServiceAddress address) throws IOException {
final var streamDetails = avatarStore.retrieveContactAvatar(address); final var streamDetails = context.getAvatarStore().retrieveContactAvatar(address);
if (streamDetails == null) { if (streamDetails == null) {
return Optional.absent(); return Optional.absent();
} }
@ -333,8 +320,9 @@ public class SyncHelper {
private void downloadContactAvatar(SignalServiceAttachment avatar, SignalServiceAddress address) { private void downloadContactAvatar(SignalServiceAttachment avatar, SignalServiceAddress address) {
try { try {
avatarStore.storeContactAvatar(address, context.getAvatarStore()
outputStream -> attachmentHelper.retrieveAttachment(avatar, outputStream)); .storeContactAvatar(address,
outputStream -> context.getAttachmentHelper().retrieveAttachment(avatar, outputStream));
} catch (IOException e) { } catch (IOException e) {
logger.warn("Failed to download avatar for contact {}, ignoring: {}", address, e.getMessage()); logger.warn("Failed to download avatar for contact {}, ignoring: {}", address, e.getMessage());
} }

View file

@ -26,22 +26,15 @@ public class UnidentifiedAccessHelper {
private final SignalAccount account; private final SignalAccount account;
private final SignalDependencies dependencies; private final SignalDependencies dependencies;
private final SelfProfileKeyProvider selfProfileKeyProvider; private final Context context;
private final ProfileProvider profileProvider;
private SenderCertificate privacySenderCertificate; private SenderCertificate privacySenderCertificate;
private SenderCertificate senderCertificate; private SenderCertificate senderCertificate;
public UnidentifiedAccessHelper( public UnidentifiedAccessHelper(final Context context) {
final SignalAccount account, this.account = context.getAccount();
final SignalDependencies dependencies, this.dependencies = context.getDependencies();
final SelfProfileKeyProvider selfProfileKeyProvider, this.context = context;
final ProfileProvider profileProvider
) {
this.account = account;
this.dependencies = dependencies;
this.selfProfileKeyProvider = selfProfileKeyProvider;
this.profileProvider = profileProvider;
} }
public List<Optional<UnidentifiedAccessPair>> getAccessFor(List<RecipientId> recipients) { public List<Optional<UnidentifiedAccessPair>> getAccessFor(List<RecipientId> recipients) {
@ -145,18 +138,18 @@ public class UnidentifiedAccessHelper {
private byte[] getSelfUnidentifiedAccessKey(boolean noRefresh) { private byte[] getSelfUnidentifiedAccessKey(boolean noRefresh) {
var selfProfile = noRefresh var selfProfile = noRefresh
? account.getProfileStore().getProfile(account.getSelfRecipientId()) ? account.getProfileStore().getProfile(account.getSelfRecipientId())
: profileProvider.getProfile(account.getSelfRecipientId()); : context.getProfileHelper().getRecipientProfile(account.getSelfRecipientId());
if (selfProfile != null if (selfProfile != null
&& selfProfile.getUnidentifiedAccessMode() == Profile.UnidentifiedAccessMode.UNRESTRICTED) { && selfProfile.getUnidentifiedAccessMode() == Profile.UnidentifiedAccessMode.UNRESTRICTED) {
return createUnrestrictedUnidentifiedAccess(); return createUnrestrictedUnidentifiedAccess();
} }
return UnidentifiedAccess.deriveAccessKeyFrom(selfProfileKeyProvider.getProfileKey()); return UnidentifiedAccess.deriveAccessKeyFrom(account.getProfileKey());
} }
private byte[] getTargetUnidentifiedAccessKey(RecipientId recipientId, boolean noRefresh) { private byte[] getTargetUnidentifiedAccessKey(RecipientId recipientId, boolean noRefresh) {
var targetProfile = noRefresh var targetProfile = noRefresh
? account.getProfileStore().getProfile(recipientId) ? account.getProfileStore().getProfile(recipientId)
: profileProvider.getProfile(recipientId); : context.getProfileHelper().getRecipientProfile(recipientId);
if (targetProfile == null) { if (targetProfile == null) {
return null; return null;
} }

View file

@ -1,10 +0,0 @@
package org.asamk.signal.manager.helper;
import org.asamk.signal.manager.storage.recipients.RecipientId;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
public interface UnidentifiedAccessProvider {
Optional<UnidentifiedAccessPair> getAccessFor(RecipientId recipientId, boolean noRefresh);
}

View file

@ -1,82 +0,0 @@
package org.asamk.signal.manager.jobs;
import org.asamk.signal.manager.SignalDependencies;
import org.asamk.signal.manager.StickerPackStore;
import org.asamk.signal.manager.helper.GroupHelper;
import org.asamk.signal.manager.helper.PreKeyHelper;
import org.asamk.signal.manager.helper.ProfileHelper;
import org.asamk.signal.manager.helper.SendHelper;
import org.asamk.signal.manager.helper.StorageHelper;
import org.asamk.signal.manager.helper.SyncHelper;
import org.asamk.signal.manager.storage.SignalAccount;
public class Context {
private final SignalAccount account;
private final SignalDependencies dependencies;
private final StickerPackStore stickerPackStore;
private final SendHelper sendHelper;
private final GroupHelper groupHelper;
private final SyncHelper syncHelper;
private final ProfileHelper profileHelper;
private final StorageHelper storageHelper;
private final PreKeyHelper preKeyHelper;
public Context(
final SignalAccount account,
final SignalDependencies dependencies,
final StickerPackStore stickerPackStore,
final SendHelper sendHelper,
final GroupHelper groupHelper,
final SyncHelper syncHelper,
final ProfileHelper profileHelper,
final StorageHelper storageHelper,
final PreKeyHelper preKeyHelper
) {
this.account = account;
this.dependencies = dependencies;
this.stickerPackStore = stickerPackStore;
this.sendHelper = sendHelper;
this.groupHelper = groupHelper;
this.syncHelper = syncHelper;
this.profileHelper = profileHelper;
this.storageHelper = storageHelper;
this.preKeyHelper = preKeyHelper;
}
public SignalAccount getAccount() {
return account;
}
public SignalDependencies getDependencies() {
return dependencies;
}
public StickerPackStore getStickerPackStore() {
return stickerPackStore;
}
public SendHelper getSendHelper() {
return sendHelper;
}
public GroupHelper getGroupHelper() {
return groupHelper;
}
public SyncHelper getSyncHelper() {
return syncHelper;
}
public ProfileHelper getProfileHelper() {
return profileHelper;
}
public StorageHelper getStorageHelper() {
return storageHelper;
}
public PreKeyHelper getPreKeyHelper() {
return preKeyHelper;
}
}

View file

@ -1,5 +1,7 @@
package org.asamk.signal.manager.jobs; package org.asamk.signal.manager.jobs;
import org.asamk.signal.manager.helper.Context;
public interface Job { public interface Job {
void run(Context context); void run(Context context);

View file

@ -1,6 +1,7 @@
package org.asamk.signal.manager.jobs; package org.asamk.signal.manager.jobs;
import org.asamk.signal.manager.JsonStickerPack; import org.asamk.signal.manager.JsonStickerPack;
import org.asamk.signal.manager.helper.Context;
import org.asamk.signal.manager.storage.stickers.StickerPackId; import org.asamk.signal.manager.storage.stickers.StickerPackId;
import org.asamk.signal.manager.util.IOUtils; import org.asamk.signal.manager.util.IOUtils;
import org.slf4j.Logger; import org.slf4j.Logger;