1 package org
.asamk
.signal
.commands
;
3 import net
.sourceforge
.argparse4j
.impl
.Arguments
;
4 import net
.sourceforge
.argparse4j
.inf
.Namespace
;
5 import net
.sourceforge
.argparse4j
.inf
.Subparser
;
7 import org
.asamk
.signal
.commands
.exceptions
.CommandException
;
8 import org
.asamk
.signal
.manager
.Manager
;
9 import org
.asamk
.signal
.manager
.storage
.recipients
.Contact
;
10 import org
.asamk
.signal
.manager
.storage
.recipients
.Profile
;
11 import org
.asamk
.signal
.output
.JsonWriter
;
12 import org
.asamk
.signal
.output
.OutputWriter
;
13 import org
.asamk
.signal
.output
.PlainTextWriter
;
14 import org
.asamk
.signal
.util
.CommandUtil
;
16 import java
.util
.Base64
;
17 import java
.util
.Optional
;
18 import java
.util
.UUID
;
20 public class ListContactsCommand
implements JsonRpcLocalCommand
{
23 public String
getName() {
24 return "listContacts";
28 public void attachToSubparser(final Subparser subparser
) {
29 subparser
.help("Show a list of known contacts with names and profiles.");
30 subparser
.addArgument("recipient").help("Specify one ore more phone numbers to show.").nargs("*");
31 subparser
.addArgument("-a", "--all-recipients")
32 .action(Arguments
.storeTrue())
33 .help("Include all known recipients, not only contacts.");
34 subparser
.addArgument("--blocked")
36 .help("Specify if only blocked or unblocked contacts should be shown (default: all contacts)");
37 subparser
.addArgument("--name").help("Find contacts with the given contact or profile name.");
41 public void handleCommand(
42 final Namespace ns
, final Manager m
, final OutputWriter outputWriter
43 ) throws CommandException
{
44 final var allRecipients
= Boolean
.TRUE
.equals(ns
.getBoolean("all-recipients"));
45 final var blocked
= ns
.getBoolean("blocked");
46 final var recipientStrings
= ns
.<String
>getList("recipient");
47 final var recipientIdentifiers
= CommandUtil
.getSingleRecipientIdentifiers(recipientStrings
, m
.getSelfNumber());
48 final var name
= ns
.getString("name");
49 final var recipients
= m
.getRecipients(!allRecipients
,
50 Optional
.ofNullable(blocked
),
52 Optional
.ofNullable(name
));
54 if (outputWriter
instanceof PlainTextWriter writer
) {
55 for (var r
: recipients
) {
56 final var contact
= r
.getContact() == null ? Contact
.newBuilder().build() : r
.getContact();
57 final var profile
= r
.getProfile() == null ? Profile
.newBuilder().build() : r
.getProfile();
58 writer
.println("Number: {} Name: {} Profile name: {} Blocked: {} Message expiration: {}",
59 r
.getAddress().getLegacyIdentifier(),
61 profile
.getDisplayName(),
63 contact
.getMessageExpirationTime() == 0
65 : contact
.getMessageExpirationTime() + "s");
68 final var writer
= (JsonWriter
) outputWriter
;
69 final var jsonContacts
= recipients
.stream().map(r
-> {
70 final var address
= r
.getAddress();
71 final var contact
= r
.getContact() == null ? Contact
.newBuilder().build() : r
.getContact();
72 return new JsonContact(address
.number().orElse(null),
73 address
.uuid().map(UUID
::toString
).orElse(null),
76 contact
.getMessageExpirationTime(),
77 r
.getProfile() == null
79 : new JsonContact
.JsonProfile(r
.getProfile().getLastUpdateTimestamp(),
80 r
.getProfile().getGivenName(),
81 r
.getProfile().getFamilyName(),
82 r
.getProfile().getAbout(),
83 r
.getProfile().getAboutEmoji(),
84 r
.getProfile().getMobileCoinAddress() == null
87 .encodeToString(r
.getProfile().getMobileCoinAddress())));
90 writer
.write(jsonContacts
);
94 private record JsonContact(
95 String number
, String uuid
, String name
, boolean isBlocked
, int messageExpirationTime
, JsonProfile profile
98 private record JsonProfile(
99 long lastUpdateTimestamp
,
104 String mobileCoinAddress