X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/20681b8d89ebaf1d437c4f6b57fefeb83dc8de45..70690fef36589a0526b23c128f409697ef086966:/src/main/java/org/asamk/signal/manager/Manager.java diff --git a/src/main/java/org/asamk/signal/manager/Manager.java b/src/main/java/org/asamk/signal/manager/Manager.java index a0f6aa53..ec427ce3 100644 --- a/src/main/java/org/asamk/signal/manager/Manager.java +++ b/src/main/java/org/asamk/signal/manager/Manager.java @@ -121,7 +121,6 @@ import org.whispersystems.signalservice.api.messages.multidevice.StickerPackOper import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; -import org.whispersystems.signalservice.api.push.ContactTokenDetails; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException; import org.whispersystems.signalservice.api.util.InvalidNumberException; @@ -288,6 +287,22 @@ public class Manager implements Closeable { return new Manager(account, pathConfig, serviceConfiguration, userAgent); } + public static List getAllLocalUsernames(File settingsPath) { + PathConfig pathConfig = PathConfig.createDefault(settingsPath); + final File dataPath = pathConfig.getDataPath(); + final File[] files = dataPath.listFiles(); + + if (files == null) { + return List.of(); + } + + return Arrays.stream(files) + .filter(File::isFile) + .map(File::getName) + .filter(file -> PhoneNumberFormatter.isValidNumber(file, null)) + .collect(Collectors.toList()); + } + public void checkAccountState() throws IOException { if (accountManager.getPreKeysCount() < ServiceConfig.PREKEY_MINIMUM_COUNT) { refreshPreKeys(); @@ -309,11 +324,9 @@ public class Manager implements Closeable { */ public Map areUsersRegistered(Set numbers) throws IOException { // Note "contactDetails" has no optionals. It only gives us info on users who are registered - List contactDetails = this.accountManager.getContacts(numbers); + Map contactDetails = getRegisteredUsers(numbers); - Set registeredUsers = contactDetails.stream() - .map(ContactTokenDetails::getNumber) - .collect(Collectors.toSet()); + Set registeredUsers = contactDetails.keySet(); return numbers.stream().collect(Collectors.toMap(x -> x, registeredUsers::contains)); } @@ -759,12 +772,10 @@ public class Manager implements Closeable { newE164Members.add(member.getNumber().get()); } - final List contacts = accountManager.getContacts(newE164Members); - if (contacts.size() != newE164Members.size()) { + final Map registeredUsers = getRegisteredUsers(newE164Members); + if (registeredUsers.size() != newE164Members.size()) { // Some of the new members are not registered on Signal - for (ContactTokenDetails contact : contacts) { - newE164Members.remove(contact.getNumber()); - } + newE164Members.removeAll(registeredUsers.keySet()); throw new IOException("Failed to add members " + String.join(", ", newE164Members) + " to group: Not registered on Signal"); @@ -937,6 +948,17 @@ public class Manager implements Closeable { return sendMessage(messageBuilder, getSignalServiceAddresses(recipients)); } + public Pair sendSelfMessage( + String messageText, List attachments + ) throws IOException, AttachmentInvalidException { + final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() + .withBody(messageText); + if (attachments != null) { + messageBuilder.withAttachments(AttachmentUtils.getSignalServiceAttachments(attachments)); + } + return sendSelfMessage(messageBuilder); + } + public Pair> sendMessageReaction( String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, List recipients ) throws IOException, InvalidNumberException { @@ -1157,28 +1179,29 @@ public class Manager implements Closeable { private Collection getSignalServiceAddresses(Collection numbers) throws InvalidNumberException { final Set signalServiceAddresses = new HashSet<>(numbers.size()); - final Set missingUuids = new HashSet<>(); + final Set addressesMissingUuid = new HashSet<>(); for (String number : numbers) { final SignalServiceAddress resolvedAddress = canonicalizeAndResolveSignalServiceAddress(number); if (resolvedAddress.getUuid().isPresent()) { signalServiceAddresses.add(resolvedAddress); } else { - missingUuids.add(resolvedAddress); + addressesMissingUuid.add(resolvedAddress); } } + final Set numbersMissingUuid = addressesMissingUuid.stream() + .map(a -> a.getNumber().get()) + .collect(Collectors.toSet()); Map registeredUsers; try { - registeredUsers = accountManager.getRegisteredUsers(getIasKeyStore(), - missingUuids.stream().map(a -> a.getNumber().get()).collect(Collectors.toSet()), - CDS_MRENCLAVE); - } catch (IOException | Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | SignatureException | UnauthenticatedResponseException e) { + registeredUsers = getRegisteredUsers(numbersMissingUuid); + } catch (IOException e) { logger.warn("Failed to resolve uuids from server, ignoring: {}", e.getMessage()); - registeredUsers = new HashMap<>(); + registeredUsers = Map.of(); } - for (SignalServiceAddress address : missingUuids) { + for (SignalServiceAddress address : addressesMissingUuid) { final String number = address.getNumber().get(); if (registeredUsers.containsKey(number)) { final SignalServiceAddress newAddress = resolveSignalServiceAddress(new SignalServiceAddress( @@ -1193,6 +1216,14 @@ public class Manager implements Closeable { return signalServiceAddresses; } + private Map getRegisteredUsers(final Set numbersMissingUuid) throws IOException { + try { + return accountManager.getRegisteredUsers(getIasKeyStore(), numbersMissingUuid, CDS_MRENCLAVE); + } catch (Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | SignatureException | UnauthenticatedResponseException e) { + throw new IOException(e); + } + } + private Pair> sendMessage( SignalServiceDataMessage.Builder messageBuilder, Collection recipients ) throws IOException { @@ -1237,11 +1268,7 @@ public class Manager implements Closeable { final int expirationTime = contact != null ? contact.messageExpirationTime : 0; messageBuilder.withExpiration(expirationTime); message = messageBuilder.build(); - if (address.matches(account.getSelfAddress())) { - results.add(sendSelfMessage(message)); - } else { - results.add(sendMessage(address, message)); - } + results.add(sendMessage(address, message)); } return new Pair<>(timestamp, results); } @@ -1255,6 +1282,28 @@ public class Manager implements Closeable { } } + private Pair sendSelfMessage( + SignalServiceDataMessage.Builder messageBuilder + ) throws IOException { + final long timestamp = System.currentTimeMillis(); + messageBuilder.withTimestamp(timestamp); + getOrCreateMessagePipe(); + getOrCreateUnidentifiedMessagePipe(); + try { + final SignalServiceAddress address = getSelfAddress(); + + final ContactInfo contact = account.getContactStore().getContact(address); + final int expirationTime = contact != null ? contact.messageExpirationTime : 0; + messageBuilder.withExpiration(expirationTime); + + SignalServiceDataMessage message = messageBuilder.build(); + final SendMessageResult result = sendSelfMessage(message); + return new Pair<>(timestamp, result); + } finally { + account.save(); + } + } + private SendMessageResult sendSelfMessage(SignalServiceDataMessage message) throws IOException { SignalServiceMessageSender messageSender = createMessageSender();