Added json output to listGroups and allowed json to be activated with -j

This commit is contained in:
david-harley 2021-01-07 15:02:47 +10:30
parent 88d81c7a63
commit 38a2da4855
4 changed files with 142 additions and 30 deletions

View file

@ -130,7 +130,7 @@ Uses a list of phone numbers to determine the statuses of those users. Shows if
[NUMBER [NUMBER ...]]::
One or more numbers to check.
*--json*::
*--j*, *--json*::
Output the statuses as an array of json objects.
=== send
@ -184,7 +184,7 @@ Number of seconds to wait for new messages (negative values disable timeout).
Default is 5 seconds.
*--ignore-attachments*::
Dont download attachments of received messages.
*--json*::
*--j*, *--json*::
Output received messages in json format, one object per line.
=== joinGroup
@ -222,10 +222,13 @@ Specify the recipient group ID in base64 encoding.
=== listGroups
Show a list of known groups.
Show a list of known groups and related information.
*-d*, *--detailed*::
Include the list of members of each group.
Include the list of members of each group and the group invite link.
*--j*, *--json*::
Output group information as a list of json objects.
=== listIdentities

View file

@ -21,7 +21,7 @@ public class GetUserStatusCommand implements LocalCommand {
public void attachToSubparser(final Subparser subparser) {
subparser.addArgument("number").help("Phone number").nargs("+");
subparser.help("Check if the specified phone number/s have been registered");
subparser.addArgument("--json")
subparser.addArgument("-j", "--json")
.help("Output received messages in json format, one json object per line.")
.action(Arguments.storeTrue());
}

View file

@ -9,32 +9,61 @@ import org.asamk.signal.manager.groups.GroupInviteLinkUrl;
import org.asamk.signal.manager.storage.groups.GroupInfo;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class ListGroupsCommand implements LocalCommand {
private static void printGroup(Manager m, GroupInfo group, boolean detailed) {
private enum MembersType {
MEMBERS,
PENDING_MEMBERS,
REQUESTING_MEMBERS,
}
private static Set<String> getMembersSet(Manager m, GroupInfo group, MembersType type) {
Set<SignalServiceAddress> members;
switch (type) {
case MEMBERS:
members = group.getMembers();
break;
case PENDING_MEMBERS:
members = group.getPendingMembers();
break;
case REQUESTING_MEMBERS:
members = group.getRequestingMembers();
break;
default:
return Collections.emptySet();
}
return members.stream().map(m::resolveSignalServiceAddress)
.map(SignalServiceAddress::getLegacyIdentifier)
.collect(Collectors.toSet());
}
private static int printGroupsJson(ObjectMapper jsonProcessor, List<?> objects) {
try {
jsonProcessor.writeValue(System.out, objects);
System.out.println();
} catch (IOException e) {
System.err.println(e.getMessage());
return 1;
}
return 0;
}
private static void printGroupPlainText(Manager m, GroupInfo group, boolean detailed) {
if (detailed) {
Set<String> members = group.getMembers()
.stream()
.map(m::resolveSignalServiceAddress)
.map(SignalServiceAddress::getLegacyIdentifier)
.collect(Collectors.toSet());
Set<String> pendingMembers = group.getPendingMembers()
.stream()
.map(m::resolveSignalServiceAddress)
.map(SignalServiceAddress::getLegacyIdentifier)
.collect(Collectors.toSet());
Set<String> requestingMembers = group.getRequestingMembers()
.stream()
.map(m::resolveSignalServiceAddress)
.map(SignalServiceAddress::getLegacyIdentifier)
.collect(Collectors.toSet());
final GroupInviteLinkUrl groupInviteLink = group.getGroupInviteLink();
System.out.println(String.format(
@ -43,9 +72,9 @@ public class ListGroupsCommand implements LocalCommand {
group.getTitle(),
group.isMember(m.getSelfAddress()),
group.isBlocked(),
members,
pendingMembers,
requestingMembers,
getMembersSet(m, group, MembersType.MEMBERS),
getMembersSet(m, group, MembersType.PENDING_MEMBERS),
getMembersSet(m, group, MembersType.REQUESTING_MEMBERS),
groupInviteLink == null ? '-' : groupInviteLink.getUrl()));
} else {
System.out.println(String.format("Id: %s Name: %s Active: %s Blocked: %b",
@ -60,6 +89,9 @@ public class ListGroupsCommand implements LocalCommand {
public void attachToSubparser(final Subparser subparser) {
subparser.addArgument("-d", "--detailed").action(Arguments.storeTrue()).help("List members of each group");
subparser.help("List group name and ids");
subparser.addArgument("-j", "--json")
.help("Output received messages in json format, one json object per line.")
.action(Arguments.storeTrue());
}
@Override
@ -72,9 +104,86 @@ public class ListGroupsCommand implements LocalCommand {
List<GroupInfo> groups = m.getGroups();
boolean detailed = ns.getBoolean("detailed");
for (GroupInfo group : groups) {
printGroup(m, group, detailed);
if (ns.getBoolean("json")) {
final ObjectMapper jsonProcessor = new ObjectMapper();
jsonProcessor.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
jsonProcessor.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
if (detailed) {
List<JsonListGroupDetailed> objects = new ArrayList<>();
for (GroupInfo group : groups) {
final GroupInviteLinkUrl groupInviteLink = group.getGroupInviteLink();
objects.add(new JsonListGroupDetailed(group.getGroupId().toBase64(),
group.getTitle(),
group.isMember(m.getSelfAddress()),
group.isBlocked(),
getMembersSet(m, group, MembersType.MEMBERS),
getMembersSet(m, group, MembersType.PENDING_MEMBERS),
getMembersSet(m, group, MembersType.REQUESTING_MEMBERS),
groupInviteLink == null ? null : groupInviteLink.getUrl()));
}
return printGroupsJson(jsonProcessor, objects);
} else {
List<JsonListGroup> objects = groups.stream().map(
group -> new JsonListGroup(group.getGroupId().toBase64(),
group.getTitle(),
group.isMember(m.getSelfAddress()),
group.isBlocked()))
.collect(Collectors.toList());
return printGroupsJson(jsonProcessor, objects);
}
} else {
for (GroupInfo group : groups) {
printGroupPlainText(m, group, detailed);
}
}
return 0;
}
private static final class JsonListGroup {
public String id;
public String name;
public boolean isMember;
public boolean isBlocked;
public JsonListGroup(String id, String name, boolean isMember, boolean isBlocked) {
this.id = id;
this.name = name;
this.isMember = isMember;
this.isBlocked = isBlocked;
}
}
private static final class JsonListGroupDetailed {
public String id;
public String name;
public boolean isMember;
public boolean isBlocked;
public Set<String> members;
public Set<String> pendingMembers;
public Set<String> requestingMembers;
public String groupInviteLink;
public JsonListGroupDetailed(String id, String name, boolean isMember, boolean isBlocked,
Set<String> members, Set<String> pendingMembers,
Set<String> requestingMembers, String groupInviteLink)
{
this.id = id;
this.name = name;
this.isMember = isMember;
this.isBlocked = isBlocked;
this.members = members;
this.pendingMembers = pendingMembers;
this.requestingMembers = requestingMembers;
this.groupInviteLink = groupInviteLink;
}
}
}

View file

@ -35,7 +35,7 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
subparser.addArgument("--ignore-attachments")
.help("Dont download attachments of received messages.")
.action(Arguments.storeTrue());
subparser.addArgument("--json")
subparser.addArgument("-j", "--json")
.help("Output received messages in json format, one json object per line.")
.action(Arguments.storeTrue());
}