]> nmode's Git Repositories - signal-cli/commitdiff
Extend json output with number and uuid fields
authorAsamK <asamk@gmx.de>
Sun, 22 Aug 2021 09:28:09 +0000 (11:28 +0200)
committerAsamK <asamk@gmx.de>
Sun, 22 Aug 2021 10:36:25 +0000 (12:36 +0200)
lib/src/main/java/org/asamk/signal/manager/Manager.java
src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java
src/main/java/org/asamk/signal/json/JsonMention.java
src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java
src/main/java/org/asamk/signal/json/JsonQuote.java
src/main/java/org/asamk/signal/json/JsonReaction.java
src/main/java/org/asamk/signal/json/JsonSyncDataMessage.java
src/main/java/org/asamk/signal/json/JsonSyncMessage.java
src/main/java/org/asamk/signal/json/JsonSyncReadMessage.java

index 9d0c355b2fe4a6674955fdb8e64b1d5928152af0..8aa7ed18574539de30e60624320a9884b0c15103 100644 (file)
@@ -327,16 +327,32 @@ public class Manager implements Closeable {
      * This is used for checking a set of phone numbers for registration on Signal
      *
      * @param numbers The set of phone number in question
-     * @return A map of numbers to booleans. True if registered, false otherwise. Should never be null
+     * @return A map of numbers to canonicalized number and uuid. If a number is not registered the uuid is null.
      * @throws IOException if its unable to get the contacts to check if they're registered
      */
-    public Map<String, Boolean> areUsersRegistered(Set<String> numbers) throws IOException {
+    public Map<String, Pair<String, UUID>> areUsersRegistered(Set<String> numbers) throws IOException {
+        Map<String, String> canonicalizedNumbers = numbers.stream().collect(Collectors.toMap(n -> n, n -> {
+            try {
+                return canonicalizePhoneNumber(n);
+            } catch (InvalidNumberException e) {
+                return "";
+            }
+        }));
+
         // Note "contactDetails" has no optionals. It only gives us info on users who are registered
-        var contactDetails = getRegisteredUsers(numbers);
+        var contactDetails = getRegisteredUsers(canonicalizedNumbers.values()
+                .stream()
+                .filter(s -> !s.isEmpty())
+                .collect(Collectors.toSet()));
 
-        var registeredUsers = contactDetails.keySet();
+        // Store numbers as recipients so we have the number/uuid association
+        contactDetails.forEach((number, uuid) -> resolveRecipientTrusted(new SignalServiceAddress(uuid, number)));
 
-        return numbers.stream().collect(Collectors.toMap(x -> x, registeredUsers::contains));
+        return numbers.stream().collect(Collectors.toMap(n -> n, n -> {
+            final var number = canonicalizedNumbers.get(n);
+            final var uuid = contactDetails.get(number);
+            return new Pair<>(number.isEmpty() ? null : number, uuid);
+        }));
     }
 
     public void updateAccountAttributes() throws IOException {
@@ -2724,14 +2740,16 @@ public class Manager implements Closeable {
         return account.getRecipientStore().resolveServiceAddress(recipientId);
     }
 
-    public RecipientId canonicalizeAndResolveRecipient(String identifier) throws InvalidNumberException {
-        var canonicalizedNumber = UuidUtil.isUuid(identifier)
-                ? identifier
-                : PhoneNumberFormatter.formatNumber(identifier, account.getUsername());
+    private RecipientId canonicalizeAndResolveRecipient(String identifier) throws InvalidNumberException {
+        var canonicalizedNumber = UuidUtil.isUuid(identifier) ? identifier : canonicalizePhoneNumber(identifier);
 
         return resolveRecipient(canonicalizedNumber);
     }
 
+    private String canonicalizePhoneNumber(final String number) throws InvalidNumberException {
+        return PhoneNumberFormatter.formatNumber(number, account.getUsername());
+    }
+
     private RecipientId resolveRecipient(final String identifier) {
         var address = Utils.getSignalServiceAddressFromIdentifier(identifier);
 
index 05bbea478696558c848dc31324806322bdd22de0..055dac9f4a7adc4f30a454e27e6e106da564232b 100644 (file)
@@ -11,10 +11,12 @@ import org.asamk.signal.commands.exceptions.IOErrorException;
 import org.asamk.signal.manager.Manager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.whispersystems.libsignal.util.Pair;
 
 import java.io.IOException;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.UUID;
 import java.util.stream.Collectors;
 
 public class GetUserStatusCommand implements JsonRpcLocalCommand {
@@ -37,7 +39,7 @@ public class GetUserStatusCommand implements JsonRpcLocalCommand {
             final Namespace ns, final Manager m, final OutputWriter outputWriter
     ) throws CommandException {
         // Get a map of registration statuses
-        Map<String, Boolean> registered;
+        Map<String, Pair<String, UUID>> registered;
         try {
             registered = m.areUsersRegistered(new HashSet<>(ns.getList("number")));
         } catch (IOException e) {
@@ -49,10 +51,11 @@ public class GetUserStatusCommand implements JsonRpcLocalCommand {
         if (outputWriter instanceof JsonWriter) {
             final var jsonWriter = (JsonWriter) outputWriter;
 
-            var jsonUserStatuses = registered.entrySet()
-                    .stream()
-                    .map(entry -> new JsonUserStatus(entry.getKey(), entry.getValue()))
-                    .collect(Collectors.toList());
+            var jsonUserStatuses = registered.entrySet().stream().map(entry -> {
+                final var number = entry.getValue().first();
+                final var uuid = entry.getValue().second();
+                return new JsonUserStatus(entry.getKey(), number, uuid == null ? null : uuid.toString(), uuid != null);
+            }).collect(Collectors.toList());
 
             jsonWriter.write(jsonUserStatuses);
         } else {
@@ -66,12 +69,18 @@ public class GetUserStatusCommand implements JsonRpcLocalCommand {
 
     private static final class JsonUserStatus {
 
-        public String name;
+        public final String name;
 
-        public boolean isRegistered;
+        public final String number;
 
-        public JsonUserStatus(String name, boolean isRegistered) {
+        public final String uuid;
+
+        public final boolean isRegistered;
+
+        public JsonUserStatus(String name, String number, String uuid, boolean isRegistered) {
             this.name = name;
+            this.number = number;
+            this.uuid = uuid;
             this.isRegistered = isRegistered;
         }
     }
index 0fe78bc2b75f5efd3b1be3318666ff82a8cad238..f0c66d00867c3df9b3cb945aab446dabe5127364 100644 (file)
@@ -6,13 +6,22 @@ import org.asamk.signal.manager.Manager;
 import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 
+import java.util.UUID;
+
 import static org.asamk.signal.util.Util.getLegacyIdentifier;
 
 public class JsonMention {
 
     @JsonProperty
+    @Deprecated
     final String name;
 
+    @JsonProperty
+    final String number;
+
+    @JsonProperty
+    final String uuid;
+
     @JsonProperty
     final int start;
 
@@ -20,8 +29,10 @@ public class JsonMention {
     final int length;
 
     JsonMention(SignalServiceDataMessage.Mention mention, Manager m) {
-        this.name = getLegacyIdentifier(m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid(),
-                null)));
+        final var address = m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid(), null));
+        this.name = getLegacyIdentifier(address);
+        this.number = address.getNumber().orNull();
+        this.uuid = address.getUuid().transform(UUID::toString).orNull();
         this.start = mention.getStart();
         this.length = mention.getLength();
     }
index 40f5ed216f39681166f53ccf73834e63920ae8f8..c7a3f8910e79bba5d6ee3d01791da69f06ade562 100644 (file)
@@ -10,14 +10,22 @@ import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
 import org.whispersystems.signalservice.api.util.InvalidNumberException;
 
 import java.util.List;
+import java.util.UUID;
 
 import static org.asamk.signal.util.Util.getLegacyIdentifier;
 
 public class JsonMessageEnvelope {
 
     @JsonProperty
+    @Deprecated
     final String source;
 
+    @JsonProperty
+    final String sourceNumber;
+
+    @JsonProperty
+    final String sourceUuid;
+
     @JsonProperty
     final String sourceName;
 
@@ -55,14 +63,21 @@ public class JsonMessageEnvelope {
         if (!envelope.isUnidentifiedSender() && envelope.hasSource()) {
             var source = envelope.getSourceAddress();
             this.source = getLegacyIdentifier(source);
+            this.sourceNumber = source.getNumber().orNull();
+            this.sourceUuid = source.getUuid().transform(UUID::toString).orNull();
             this.sourceDevice = envelope.getSourceDevice();
             this.relay = source.getRelay().orNull();
         } else if (envelope.isUnidentifiedSender() && content != null) {
-            this.source = getLegacyIdentifier(content.getSender());
+            final var source = content.getSender();
+            this.source = getLegacyIdentifier(source);
+            this.sourceNumber = source.getNumber().orNull();
+            this.sourceUuid = source.getUuid().transform(UUID::toString).orNull();
             this.sourceDevice = content.getSenderDevice();
             this.relay = null;
         } else {
             this.source = null;
+            this.sourceNumber = null;
+            this.sourceUuid = null;
             this.sourceDevice = null;
             this.relay = null;
         }
@@ -98,6 +113,8 @@ public class JsonMessageEnvelope {
 
     public JsonMessageEnvelope(Signal.MessageReceived messageReceived) {
         source = messageReceived.getSender();
+        sourceNumber = null;
+        sourceUuid = null;
         sourceName = null;
         sourceDevice = null;
         relay = null;
@@ -111,6 +128,8 @@ public class JsonMessageEnvelope {
 
     public JsonMessageEnvelope(Signal.ReceiptReceived receiptReceived) {
         source = receiptReceived.getSender();
+        sourceNumber = null;
+        sourceUuid = null;
         sourceName = null;
         sourceDevice = null;
         relay = null;
@@ -124,6 +143,8 @@ public class JsonMessageEnvelope {
 
     public JsonMessageEnvelope(Signal.SyncMessageReceived messageReceived) {
         source = messageReceived.getSource();
+        sourceNumber = null;
+        sourceUuid = null;
         sourceName = null;
         sourceDevice = null;
         relay = null;
index f90b492d135b23334adbe00b7de6cacb26860005..ecd31c1af183a419ca0fde0dd2adeeee52d83d6c 100644 (file)
@@ -8,6 +8,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.UUID;
 import java.util.stream.Collectors;
 
 import static org.asamk.signal.util.Util.getLegacyIdentifier;
@@ -18,8 +19,15 @@ public class JsonQuote {
     final long id;
 
     @JsonProperty
+    @Deprecated
     final String author;
 
+    @JsonProperty
+    final String authorNumber;
+
+    @JsonProperty
+    final String authorUuid;
+
     @JsonProperty
     final String text;
 
@@ -32,7 +40,10 @@ public class JsonQuote {
 
     JsonQuote(SignalServiceDataMessage.Quote quote, Manager m) {
         this.id = quote.getId();
-        this.author = getLegacyIdentifier(m.resolveSignalServiceAddress(quote.getAuthor()));
+        final var address = m.resolveSignalServiceAddress(quote.getAuthor());
+        this.author = getLegacyIdentifier(address);
+        this.authorNumber = address.getNumber().orNull();
+        this.authorUuid = address.getUuid().transform(UUID::toString).orNull();
         this.text = quote.getText();
 
         if (quote.getMentions() != null && quote.getMentions().size() > 0) {
index e7d40fbeb9308d3bcfd55577453338e009bcbf70..ecea15fe1ef71fa8f1ee09a88e1f89651c6172cb 100644 (file)
@@ -5,6 +5,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import org.asamk.signal.manager.Manager;
 import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Reaction;
 
+import java.util.UUID;
+
 import static org.asamk.signal.util.Util.getLegacyIdentifier;
 
 public class JsonReaction {
@@ -13,8 +15,15 @@ public class JsonReaction {
     final String emoji;
 
     @JsonProperty
+    @Deprecated
     final String targetAuthor;
 
+    @JsonProperty
+    final String targetAuthorNumber;
+
+    @JsonProperty
+    final String targetAuthorUuid;
+
     @JsonProperty
     final long targetSentTimestamp;
 
@@ -23,7 +32,10 @@ public class JsonReaction {
 
     JsonReaction(Reaction reaction, Manager m) {
         this.emoji = reaction.getEmoji();
-        this.targetAuthor = getLegacyIdentifier(m.resolveSignalServiceAddress(reaction.getTargetAuthor()));
+        final var address = m.resolveSignalServiceAddress(reaction.getTargetAuthor());
+        this.targetAuthor = getLegacyIdentifier(address);
+        this.targetAuthorNumber = address.getNumber().orNull();
+        this.targetAuthorUuid = address.getUuid().transform(UUID::toString).orNull();
         this.targetSentTimestamp = reaction.getTargetSentTimestamp();
         this.isRemove = reaction.isRemove();
     }
index c9d887902e89023e7bbf5428d86bd502e4a826e2..28c9d9369403a41fdd95d87bea0a082e21e2594f 100644 (file)
@@ -4,22 +4,43 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 
 import org.asamk.Signal;
 import org.asamk.signal.manager.Manager;
-import org.asamk.signal.util.Util;
 import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage;
 
+import java.util.UUID;
+
+import static org.asamk.signal.util.Util.getLegacyIdentifier;
+
 class JsonSyncDataMessage extends JsonDataMessage {
 
     @JsonProperty
+    @Deprecated
     final String destination;
 
+    @JsonProperty
+    final String destinationNumber;
+
+    @JsonProperty
+    final String destinationUuid;
+
     JsonSyncDataMessage(SentTranscriptMessage transcriptMessage, Manager m) {
         super(transcriptMessage.getMessage(), m);
 
-        this.destination = transcriptMessage.getDestination().transform(Util::getLegacyIdentifier).orNull();
+        if (transcriptMessage.getDestination().isPresent()) {
+            final var address = transcriptMessage.getDestination().get();
+            this.destination = getLegacyIdentifier(address);
+            this.destinationNumber = address.getNumber().orNull();
+            this.destinationUuid = address.getUuid().transform(UUID::toString).orNull();
+        } else {
+            this.destination = null;
+            this.destinationNumber = null;
+            this.destinationUuid = null;
+        }
     }
 
     JsonSyncDataMessage(Signal.SyncMessageReceived messageReceived) {
         super(messageReceived);
-        destination = messageReceived.getDestination();
+        this.destination = messageReceived.getDestination();
+        this.destinationNumber = null;
+        this.destinationUuid = null;
     }
 }
index 6e992bcb0be0232c4fc0978e90bb7fadd10c6a17..5c951f0f16c0f60623c962215600cb7f6b99a596 100644 (file)
@@ -12,8 +12,6 @@ import java.util.Base64;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import static org.asamk.signal.util.Util.getLegacyIdentifier;
-
 enum JsonSyncMessageType {
     CONTACTS_SYNC,
     GROUPS_SYNC,
@@ -68,8 +66,7 @@ class JsonSyncMessage {
             this.readMessages = syncMessage.getRead()
                     .get()
                     .stream()
-                    .map(message -> new JsonSyncReadMessage(getLegacyIdentifier(message.getSender()),
-                            message.getTimestamp()))
+                    .map(JsonSyncReadMessage::new)
                     .collect(Collectors.toList());
         } else {
             this.readMessages = null;
index d65b0672097770a2af54333dde56d34a6cf85958..df307b45cbb10f0a9abcc5ff382254e788913b7e 100644 (file)
@@ -2,16 +2,32 @@ package org.asamk.signal.json;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 
+import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage;
+
+import java.util.UUID;
+
+import static org.asamk.signal.util.Util.getLegacyIdentifier;
+
 class JsonSyncReadMessage {
 
     @JsonProperty
+    @Deprecated
     final String sender;
 
+    @JsonProperty
+    final String senderNumber;
+
+    @JsonProperty
+    final String senderUuid;
+
     @JsonProperty
     final long timestamp;
 
-    public JsonSyncReadMessage(final String sender, final long timestamp) {
-        this.sender = sender;
-        this.timestamp = timestamp;
+    public JsonSyncReadMessage(final ReadMessage readMessage) {
+        final var sender = readMessage.getSender();
+        this.sender = getLegacyIdentifier(sender);
+        this.senderNumber = sender.getNumber().orNull();
+        this.senderUuid = sender.getUuid().transform(UUID::toString).orNull();
+        this.timestamp = readMessage.getTimestamp();
     }
 }