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
.JsonWriter
;
8 import org
.asamk
.signal
.OutputType
;
9 import org
.asamk
.signal
.manager
.Manager
;
10 import org
.asamk
.signal
.manager
.storage
.groups
.GroupInfo
;
11 import org
.slf4j
.Logger
;
12 import org
.slf4j
.LoggerFactory
;
13 import org
.whispersystems
.signalservice
.api
.push
.SignalServiceAddress
;
15 import java
.io
.IOException
;
16 import java
.util
.ArrayList
;
18 import java
.util
.stream
.Collectors
;
20 public class ListGroupsCommand
implements LocalCommand
{
22 private final static Logger logger
= LoggerFactory
.getLogger(ListGroupsCommand
.class);
24 private static Set
<String
> resolveMembers(Manager m
, Set
<SignalServiceAddress
> addresses
) {
25 return addresses
.stream()
26 .map(m
::resolveSignalServiceAddress
)
27 .map(SignalServiceAddress
::getLegacyIdentifier
)
28 .collect(Collectors
.toSet());
31 private static void printGroupPlainText(Manager m
, GroupInfo group
, boolean detailed
) {
33 final var groupInviteLink
= group
.getGroupInviteLink();
35 System
.out
.println(String
.format(
36 "Id: %s Name: %s Active: %s Blocked: %b Members: %s Pending members: %s Requesting members: %s Link: %s",
37 group
.getGroupId().toBase64(),
39 group
.isMember(m
.getSelfAddress()),
41 resolveMembers(m
, group
.getMembers()),
42 resolveMembers(m
, group
.getPendingMembers()),
43 resolveMembers(m
, group
.getRequestingMembers()),
44 groupInviteLink
== null ?
'-' : groupInviteLink
.getUrl()));
46 System
.out
.println(String
.format("Id: %s Name: %s Active: %s Blocked: %b",
47 group
.getGroupId().toBase64(),
49 group
.isMember(m
.getSelfAddress()),
55 public void attachToSubparser(final Subparser subparser
) {
56 subparser
.addArgument("-d", "--detailed")
57 .action(Arguments
.storeTrue())
58 .help("List the members and group invite links of each group. If output=json, then this is always set");
60 subparser
.help("List group information including names, ids, active status, blocked status and members");
64 public Set
<OutputType
> getSupportedOutputTypes() {
65 return Set
.of(OutputType
.PLAIN_TEXT
, OutputType
.JSON
);
69 public int handleCommand(final Namespace ns
, final Manager m
) {
70 if (ns
.get("output") == OutputType
.JSON
) {
71 final var jsonWriter
= new JsonWriter(System
.out
);
73 var jsonGroups
= new ArrayList
<JsonGroup
>();
74 for (var group
: m
.getGroups()) {
75 final var groupInviteLink
= group
.getGroupInviteLink();
77 jsonGroups
.add(new JsonGroup(group
.getGroupId().toBase64(),
79 group
.isMember(m
.getSelfAddress()),
81 resolveMembers(m
, group
.getMembers()),
82 resolveMembers(m
, group
.getPendingMembers()),
83 resolveMembers(m
, group
.getRequestingMembers()),
84 groupInviteLink
== null ?
null : groupInviteLink
.getUrl()));
88 jsonWriter
.write(jsonGroups
);
89 } catch (IOException e
) {
90 logger
.error("Failed to write json object: {}", e
.getMessage());
96 boolean detailed
= ns
.getBoolean("detailed");
97 for (var group
: m
.getGroups()) {
98 printGroupPlainText(m
, group
, detailed
);
105 private static final class JsonGroup
{
109 public boolean isMember
;
110 public boolean isBlocked
;
112 public Set
<String
> members
;
113 public Set
<String
> pendingMembers
;
114 public Set
<String
> requestingMembers
;
115 public String groupInviteLink
;
123 Set
<String
> pendingMembers
,
124 Set
<String
> requestingMembers
,
125 String groupInviteLink
129 this.isMember
= isMember
;
130 this.isBlocked
= isBlocked
;
132 this.members
= members
;
133 this.pendingMembers
= pendingMembers
;
134 this.requestingMembers
= requestingMembers
;
135 this.groupInviteLink
= groupInviteLink
;