Add more details to listContacts command

Fixes #1502
This commit is contained in:
AsamK 2024-04-17 21:26:16 +02:00
parent 8aeaf927e6
commit e4c5144fbf
4 changed files with 143 additions and 25 deletions

View 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
) {}
}
}

View file

@ -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
) {}
}