mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 02:20:39 +00:00
parent
8aeaf927e6
commit
e4c5144fbf
4 changed files with 143 additions and 25 deletions
|
@ -849,6 +849,24 @@
|
||||||
"queryAllDeclaredConstructors":true,
|
"queryAllDeclaredConstructors":true,
|
||||||
"methods":[{"name":"id","parameterTypes":[] }, {"name":"opaque","parameterTypes":[] }, {"name":"sdp","parameterTypes":[] }, {"name":"type","parameterTypes":[] }]
|
"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",
|
"name":"org.asamk.signal.json.JsonContactAddress",
|
||||||
"allDeclaredFields":true,
|
"allDeclaredFields":true,
|
||||||
|
|
|
@ -590,6 +590,12 @@ Specify if only blocked or unblocked contacts should be shown (default: all cont
|
||||||
*--name*::
|
*--name*::
|
||||||
Find contacts with the given contact or profile 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
|
=== listIdentities
|
||||||
|
|
||||||
List all known identity keys and their trust status, fingerprint and safety number.
|
List all known identity keys and their trust status, fingerprint and safety number.
|
||||||
|
|
|
@ -5,8 +5,10 @@ import net.sourceforge.argparse4j.inf.Namespace;
|
||||||
import net.sourceforge.argparse4j.inf.Subparser;
|
import net.sourceforge.argparse4j.inf.Subparser;
|
||||||
|
|
||||||
import org.asamk.signal.commands.exceptions.CommandException;
|
import org.asamk.signal.commands.exceptions.CommandException;
|
||||||
|
import org.asamk.signal.json.JsonContact;
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.api.Contact;
|
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.manager.api.Profile;
|
||||||
import org.asamk.signal.output.JsonWriter;
|
import org.asamk.signal.output.JsonWriter;
|
||||||
import org.asamk.signal.output.OutputWriter;
|
import org.asamk.signal.output.OutputWriter;
|
||||||
|
@ -35,6 +37,12 @@ public class ListContactsCommand implements JsonRpcLocalCommand {
|
||||||
.type(Boolean.class)
|
.type(Boolean.class)
|
||||||
.help("Specify if only blocked or unblocked contacts should be shown (default: all contacts)");
|
.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("--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
|
@Override
|
||||||
|
@ -51,33 +59,94 @@ public class ListContactsCommand implements JsonRpcLocalCommand {
|
||||||
recipientIdentifiers,
|
recipientIdentifiers,
|
||||||
Optional.ofNullable(name));
|
Optional.ofNullable(name));
|
||||||
|
|
||||||
|
final var detailed = Boolean.TRUE.equals(ns.getBoolean("detailed"));
|
||||||
|
final var internal = Boolean.TRUE.equals(ns.getBoolean("internal"));
|
||||||
|
|
||||||
switch (outputWriter) {
|
switch (outputWriter) {
|
||||||
case PlainTextWriter writer -> {
|
case PlainTextWriter writer -> {
|
||||||
for (var r : recipients) {
|
for (var r : recipients) {
|
||||||
final var contact = r.getContact() == null ? Contact.newBuilder().build() : r.getContact();
|
final var contact = r.getContact() == null ? Contact.newBuilder().build() : r.getContact();
|
||||||
final var profile = r.getProfile() == null ? Profile.newBuilder().build() : r.getProfile();
|
final var profile = r.getProfile() == null ? Profile.newBuilder().build() : r.getProfile();
|
||||||
writer.println(
|
writer.println(
|
||||||
"Number: {} Name: {} Profile name: {} Username: {} Color: {} Blocked: {} Message expiration: {}",
|
"Number: {} ACI: {} Name: {} Profile name: {} Username: {} Color: {} Blocked: {} Message expiration: {}",
|
||||||
r.getAddress().getLegacyIdentifier(),
|
r.getAddress().number().orElse(""),
|
||||||
|
r.getAddress().aci().orElse(""),
|
||||||
contact.getName(),
|
contact.getName(),
|
||||||
profile.getDisplayName(),
|
profile.getDisplayName(),
|
||||||
r.getAddress().username().orElse(""),
|
r.getAddress().username().orElse(""),
|
||||||
contact.color(),
|
Optional.ofNullable(contact.color()).orElse(""),
|
||||||
contact.isBlocked(),
|
contact.isBlocked(),
|
||||||
contact.messageExpirationTime() == 0 ? "disabled" : contact.messageExpirationTime() + "s");
|
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 -> {
|
case JsonWriter writer -> {
|
||||||
final var jsonContacts = recipients.stream().map(r -> {
|
final var jsonContacts = recipients.stream().map(r -> {
|
||||||
final var address = r.getAddress();
|
final var address = r.getAddress();
|
||||||
final var contact = r.getContact() == null ? Contact.newBuilder().build() : r.getContact();
|
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),
|
return new JsonContact(address.number().orElse(null),
|
||||||
address.uuid().map(UUID::toString).orElse(null),
|
address.uuid().map(UUID::toString).orElse(null),
|
||||||
address.username().orElse(null),
|
address.username().orElse(null),
|
||||||
contact.getName(),
|
contact.getName(),
|
||||||
|
contact.givenName(),
|
||||||
|
contact.familyName(),
|
||||||
|
contact.nickName(),
|
||||||
|
contact.nickNameGivenName(),
|
||||||
|
contact.nickNameFamilyName(),
|
||||||
|
contact.note(),
|
||||||
contact.color(),
|
contact.color(),
|
||||||
contact.isBlocked(),
|
contact.isBlocked(),
|
||||||
|
contact.isHidden(),
|
||||||
contact.messageExpirationTime(),
|
contact.messageExpirationTime(),
|
||||||
|
r.getContact().isProfileSharingEnabled(),
|
||||||
|
r.getContact().unregisteredTimestamp() != null,
|
||||||
r.getProfile() == null
|
r.getProfile() == null
|
||||||
? null
|
? null
|
||||||
: new JsonContact.JsonProfile(r.getProfile().getLastUpdateTimestamp(),
|
: new JsonContact.JsonProfile(r.getProfile().getLastUpdateTimestamp(),
|
||||||
|
@ -85,34 +154,15 @@ public class ListContactsCommand implements JsonRpcLocalCommand {
|
||||||
r.getProfile().getFamilyName(),
|
r.getProfile().getFamilyName(),
|
||||||
r.getProfile().getAbout(),
|
r.getProfile().getAbout(),
|
||||||
r.getProfile().getAboutEmoji(),
|
r.getProfile().getAboutEmoji(),
|
||||||
|
r.getProfile().getAvatarUrlPath() != null,
|
||||||
r.getProfile().getMobileCoinAddress() == null
|
r.getProfile().getMobileCoinAddress() == null
|
||||||
? null
|
? null
|
||||||
: Base64.getEncoder()
|
: Base64.getEncoder()
|
||||||
.encodeToString(r.getProfile().getMobileCoinAddress())));
|
.encodeToString(r.getProfile().getMobileCoinAddress())),
|
||||||
|
jsonInternal);
|
||||||
}).toList();
|
}).toList();
|
||||||
writer.write(jsonContacts);
|
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
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
44
src/main/java/org/asamk/signal/json/JsonContact.java
Normal file
44
src/main/java/org/asamk/signal/json/JsonContact.java
Normal 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
|
||||||
|
) {}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue