]> nmode's Git Repositories - signal-cli/commitdiff
Add more details to listContacts command
authorAsamK <asamk@gmx.de>
Wed, 17 Apr 2024 19:26:16 +0000 (21:26 +0200)
committerAsamK <asamk@gmx.de>
Wed, 17 Apr 2024 19:26:16 +0000 (21:26 +0200)
Fixes #1502

graalvm-config-dir/reflect-config.json
man/signal-cli.1.adoc
src/main/java/org/asamk/signal/commands/ListContactsCommand.java
src/main/java/org/asamk/signal/json/JsonContact.java [new file with mode: 0644]

index 252839b2f8b5e599cc7c830803efd5c4d8512a7a..c6e85760e6da37e061261998ccef8979d671fd54 100644 (file)
   "queryAllDeclaredConstructors":true,
   "methods":[{"name":"id","parameterTypes":[] }, {"name":"opaque","parameterTypes":[] }, {"name":"sdp","parameterTypes":[] }, {"name":"type","parameterTypes":[] }]
 },
+{
+  "name":"org.asamk.signal.json.JsonContact",
+  "allDeclaredFields":true,
+  "queryAllDeclaredMethods":true,
+  "methods":[{"name":"color","parameterTypes":[] }, {"name":"familyName","parameterTypes":[] }, {"name":"givenName","parameterTypes":[] }, {"name":"internal","parameterTypes":[] }, {"name":"isBlocked","parameterTypes":[] }, {"name":"isHidden","parameterTypes":[] }, {"name":"messageExpirationTime","parameterTypes":[] }, {"name":"name","parameterTypes":[] }, {"name":"nickFamilyName","parameterTypes":[] }, {"name":"nickGivenName","parameterTypes":[] }, {"name":"nickName","parameterTypes":[] }, {"name":"note","parameterTypes":[] }, {"name":"number","parameterTypes":[] }, {"name":"profile","parameterTypes":[] }, {"name":"profileSharing","parameterTypes":[] }, {"name":"unregistered","parameterTypes":[] }, {"name":"username","parameterTypes":[] }, {"name":"uuid","parameterTypes":[] }]
+},
+{
+  "name":"org.asamk.signal.json.JsonContact$JsonInternal",
+  "allDeclaredFields":true,
+  "queryAllDeclaredMethods":true,
+  "methods":[{"name":"capabilities","parameterTypes":[] }, {"name":"discoverableByPhonenumber","parameterTypes":[] }, {"name":"sharesPhoneNumber","parameterTypes":[] }, {"name":"unidentifiedAccessMode","parameterTypes":[] }]
+},
+{
+  "name":"org.asamk.signal.json.JsonContact$JsonProfile",
+  "allDeclaredFields":true,
+  "queryAllDeclaredMethods":true,
+  "methods":[{"name":"about","parameterTypes":[] }, {"name":"aboutEmoji","parameterTypes":[] }, {"name":"familyName","parameterTypes":[] }, {"name":"givenName","parameterTypes":[] }, {"name":"hasAvatar","parameterTypes":[] }, {"name":"lastUpdateTimestamp","parameterTypes":[] }, {"name":"mobileCoinAddress","parameterTypes":[] }]
+},
 {
   "name":"org.asamk.signal.json.JsonContactAddress",
   "allDeclaredFields":true,
index 31bc5499b5784a2a2637dc92105c5f89f58f7434..7335eba6ce45e19ba06187c377ba19d0fb3aa0c7 100644 (file)
@@ -590,6 +590,12 @@ Specify if only blocked or unblocked contacts should be shown (default: all cont
 *--name*::
 Find contacts with the given contact or profile name.
 
+*--detailed*::
+List the contacts with more details. If output=json, then this is always set
+
+*--internal*::
+Include internal information that's normally not user visible
+
 === listIdentities
 
 List all known identity keys and their trust status, fingerprint and safety number.
index 698e6f2bdc6777208484433a896749841adfde56..3865d829effdf6ca757a5338b054f2d9d10a5b93 100644 (file)
@@ -5,8 +5,10 @@ import net.sourceforge.argparse4j.inf.Namespace;
 import net.sourceforge.argparse4j.inf.Subparser;
 
 import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.json.JsonContact;
 import org.asamk.signal.manager.Manager;
 import org.asamk.signal.manager.api.Contact;
+import org.asamk.signal.manager.api.PhoneNumberSharingMode;
 import org.asamk.signal.manager.api.Profile;
 import org.asamk.signal.output.JsonWriter;
 import org.asamk.signal.output.OutputWriter;
@@ -35,6 +37,12 @@ public class ListContactsCommand implements JsonRpcLocalCommand {
                 .type(Boolean.class)
                 .help("Specify if only blocked or unblocked contacts should be shown (default: all contacts)");
         subparser.addArgument("--name").help("Find contacts with the given contact or profile name.");
+        subparser.addArgument("--detailed")
+                .action(Arguments.storeTrue())
+                .help("List the contacts with more details. If output=json, then this is always set");
+        subparser.addArgument("--internal")
+                .action(Arguments.storeTrue())
+                .help("Include internal information that's normally not user visible");
     }
 
     @Override
@@ -51,33 +59,94 @@ public class ListContactsCommand implements JsonRpcLocalCommand {
                 recipientIdentifiers,
                 Optional.ofNullable(name));
 
+        final var detailed = Boolean.TRUE.equals(ns.getBoolean("detailed"));
+        final var internal = Boolean.TRUE.equals(ns.getBoolean("internal"));
+
         switch (outputWriter) {
             case PlainTextWriter writer -> {
                 for (var r : recipients) {
                     final var contact = r.getContact() == null ? Contact.newBuilder().build() : r.getContact();
                     final var profile = r.getProfile() == null ? Profile.newBuilder().build() : r.getProfile();
                     writer.println(
-                            "Number: {} Name: {} Profile name: {} Username: {} Color: {} Blocked: {} Message expiration: {}",
-                            r.getAddress().getLegacyIdentifier(),
+                            "Number: {} ACI: {} Name: {} Profile name: {} Username: {} Color: {} Blocked: {} Message expiration: {}",
+                            r.getAddress().number().orElse(""),
+                            r.getAddress().aci().orElse(""),
                             contact.getName(),
                             profile.getDisplayName(),
                             r.getAddress().username().orElse(""),
-                            contact.color(),
+                            Optional.ofNullable(contact.color()).orElse(""),
                             contact.isBlocked(),
                             contact.messageExpirationTime() == 0 ? "disabled" : contact.messageExpirationTime() + "s");
+                    if (detailed) {
+                        writer.indentedWriter()
+                                .println(
+                                        "PNI: {} Given name: {} Family name: {}, Nick name: {} Nick given name: {} Nick family name {} Note: {} Archived: {} Hidden: {} Profile sharing: {} About: {} About Emoji: {} Unregistered: {}",
+                                        r.getAddress().pni().orElse(""),
+                                        Optional.ofNullable(r.getContact().givenName()).orElse(""),
+                                        Optional.ofNullable(r.getContact().familyName()).orElse(""),
+                                        Optional.ofNullable(r.getContact().nickName()).orElse(""),
+                                        Optional.ofNullable(r.getContact().nickNameGivenName()).orElse(""),
+                                        Optional.ofNullable(r.getContact().nickNameFamilyName()).orElse(""),
+                                        Optional.ofNullable(r.getContact().note()).orElse(""),
+                                        r.getContact().isArchived(),
+                                        r.getContact().isHidden(),
+                                        r.getContact().isProfileSharingEnabled(),
+                                        Optional.ofNullable(r.getProfile().getAbout()).orElse(""),
+                                        Optional.ofNullable(r.getProfile().getAboutEmoji()).orElse(""),
+                                        r.getContact().unregisteredTimestamp() != null);
+                    }
+                    if (internal) {
+                        writer.indentedWriter()
+                                .println(
+                                        "Capabilities: {} Unidentified access mode: {} Shares number: {} Discoverable by number: {}",
+                                        r.getProfile().getCapabilities().stream().map(Enum::name).toList(),
+                                        Optional.ofNullable(r.getProfile().getUnidentifiedAccessMode()
+                                                == Profile.UnidentifiedAccessMode.UNKNOWN
+                                                ? null
+                                                : r.getProfile().getUnidentifiedAccessMode().name()).orElse(""),
+                                        r.getProfile().getPhoneNumberSharingMode() == null
+                                                ? ""
+                                                : String.valueOf(r.getProfile().getPhoneNumberSharingMode()
+                                                        == PhoneNumberSharingMode.EVERYBODY),
+                                        r.getDiscoverable() == null ? "" : String.valueOf(r.getDiscoverable()));
+                    }
                 }
             }
             case JsonWriter writer -> {
                 final var jsonContacts = recipients.stream().map(r -> {
                     final var address = r.getAddress();
                     final var contact = r.getContact() == null ? Contact.newBuilder().build() : r.getContact();
+                    final var jsonInternal = !internal
+                            ? null
+                            : new JsonContact.JsonInternal(r.getProfile()
+                                    .getCapabilities()
+                                    .stream()
+                                    .map(Enum::name)
+                                    .toList(),
+                                    r.getProfile().getUnidentifiedAccessMode() == Profile.UnidentifiedAccessMode.UNKNOWN
+                                            ? null
+                                            : r.getProfile().getUnidentifiedAccessMode().name(),
+                                    r.getProfile().getPhoneNumberSharingMode() == null
+                                            ? null
+                                            : r.getProfile().getPhoneNumberSharingMode()
+                                                    == PhoneNumberSharingMode.EVERYBODY,
+                                    r.getDiscoverable());
                     return new JsonContact(address.number().orElse(null),
                             address.uuid().map(UUID::toString).orElse(null),
                             address.username().orElse(null),
                             contact.getName(),
+                            contact.givenName(),
+                            contact.familyName(),
+                            contact.nickName(),
+                            contact.nickNameGivenName(),
+                            contact.nickNameFamilyName(),
+                            contact.note(),
                             contact.color(),
                             contact.isBlocked(),
+                            contact.isHidden(),
                             contact.messageExpirationTime(),
+                            r.getContact().isProfileSharingEnabled(),
+                            r.getContact().unregisteredTimestamp() != null,
                             r.getProfile() == null
                                     ? null
                                     : new JsonContact.JsonProfile(r.getProfile().getLastUpdateTimestamp(),
@@ -85,34 +154,15 @@ public class ListContactsCommand implements JsonRpcLocalCommand {
                                             r.getProfile().getFamilyName(),
                                             r.getProfile().getAbout(),
                                             r.getProfile().getAboutEmoji(),
+                                            r.getProfile().getAvatarUrlPath() != null,
                                             r.getProfile().getMobileCoinAddress() == null
                                                     ? null
                                                     : Base64.getEncoder()
-                                                            .encodeToString(r.getProfile().getMobileCoinAddress())));
+                                                            .encodeToString(r.getProfile().getMobileCoinAddress())),
+                            jsonInternal);
                 }).toList();
                 writer.write(jsonContacts);
             }
         }
     }
-
-    private record JsonContact(
-            String number,
-            String uuid,
-            String username,
-            String name,
-            String color,
-            boolean isBlocked,
-            int messageExpirationTime,
-            JsonProfile profile
-    ) {
-
-        private record JsonProfile(
-                long lastUpdateTimestamp,
-                String givenName,
-                String familyName,
-                String about,
-                String aboutEmoji,
-                String mobileCoinAddress
-        ) {}
-    }
 }
diff --git a/src/main/java/org/asamk/signal/json/JsonContact.java b/src/main/java/org/asamk/signal/json/JsonContact.java
new file mode 100644 (file)
index 0000000..71f05c8
--- /dev/null
@@ -0,0 +1,44 @@
+package org.asamk.signal.json;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import java.util.List;
+
+public record JsonContact(
+        String number,
+        String uuid,
+        String username,
+        String name,
+        String givenName,
+        String familyName,
+        String nickName,
+        String nickGivenName,
+        String nickFamilyName,
+        String note,
+        String color,
+        boolean isBlocked,
+        boolean isHidden,
+        int messageExpirationTime,
+        boolean profileSharing,
+        boolean unregistered,
+        JsonProfile profile,
+        @JsonInclude(JsonInclude.Include.NON_NULL) JsonInternal internal
+) {
+
+    public record JsonProfile(
+            long lastUpdateTimestamp,
+            String givenName,
+            String familyName,
+            String about,
+            String aboutEmoji,
+            boolean hasAvatar,
+            String mobileCoinAddress
+    ) {}
+
+    public record JsonInternal(
+            List<String> capabilities,
+            String unidentifiedAccessMode,
+            Boolean sharesPhoneNumber,
+            Boolean discoverableByPhonenumber
+    ) {}
+}