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
.OutputWriter
;
9 import org
.asamk
.signal
.PlainTextWriter
;
10 import org
.asamk
.signal
.commands
.exceptions
.CommandException
;
11 import org
.asamk
.signal
.manager
.Manager
;
12 import org
.asamk
.signal
.manager
.storage
.groups
.GroupInfo
;
13 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientId
;
14 import org
.asamk
.signal
.util
.Util
;
15 import org
.slf4j
.Logger
;
16 import org
.slf4j
.LoggerFactory
;
19 import java
.util
.UUID
;
20 import java
.util
.stream
.Collectors
;
22 public class ListGroupsCommand
implements JsonRpcLocalCommand
{
24 private final static Logger logger
= LoggerFactory
.getLogger(ListGroupsCommand
.class);
27 public String
getName() {
32 public void attachToSubparser(final Subparser subparser
) {
33 subparser
.help("List group information including names, ids, active status, blocked status and members");
34 subparser
.addArgument("-d", "--detailed")
35 .action(Arguments
.storeTrue())
36 .help("List the members and group invite links of each group. If output=json, then this is always set");
39 private static Set
<String
> resolveMembers(Manager m
, Set
<RecipientId
> addresses
) {
40 return addresses
.stream()
41 .map(m
::resolveSignalServiceAddress
)
42 .map(Util
::getLegacyIdentifier
)
43 .collect(Collectors
.toSet());
46 private static Set
<JsonGroupMember
> resolveJsonMembers(Manager m
, Set
<RecipientId
> addresses
) {
47 return addresses
.stream()
48 .map(m
::resolveSignalServiceAddress
)
49 .map(address
-> new JsonGroupMember(address
.getNumber().orNull(),
50 address
.getUuid().transform(UUID
::toString
).orNull()))
51 .collect(Collectors
.toSet());
54 private static void printGroupPlainText(
55 PlainTextWriter writer
, Manager m
, GroupInfo group
, boolean detailed
58 final var groupInviteLink
= group
.getGroupInviteLink();
61 "Id: {} Name: {} Description: {} Active: {} Blocked: {} Members: {} Pending members: {} Requesting members: {} Admins: {} Message expiration: {} Link: {}",
62 group
.getGroupId().toBase64(),
64 group
.getDescription(),
65 group
.isMember(m
.getSelfRecipientId()),
67 resolveMembers(m
, group
.getMembers()),
68 resolveMembers(m
, group
.getPendingMembers()),
69 resolveMembers(m
, group
.getRequestingMembers()),
70 resolveMembers(m
, group
.getAdminMembers()),
71 group
.getMessageExpirationTime() == 0 ?
"disabled" : group
.getMessageExpirationTime() + "s",
72 groupInviteLink
== null ?
'-' : groupInviteLink
.getUrl());
74 writer
.println("Id: {} Name: {} Active: {} Blocked: {}",
75 group
.getGroupId().toBase64(),
77 group
.isMember(m
.getSelfRecipientId()),
83 public void handleCommand(
84 final Namespace ns
, final Manager m
, final OutputWriter outputWriter
85 ) throws CommandException
{
86 final var groups
= m
.getGroups();
88 if (outputWriter
instanceof JsonWriter
) {
89 final var jsonWriter
= (JsonWriter
) outputWriter
;
91 var jsonGroups
= groups
.stream().map(group
-> {
92 final var groupInviteLink
= group
.getGroupInviteLink();
94 return new JsonGroup(group
.getGroupId().toBase64(),
96 group
.getDescription(),
97 group
.isMember(m
.getSelfRecipientId()),
99 group
.getMessageExpirationTime(),
100 resolveJsonMembers(m
, group
.getMembers()),
101 resolveJsonMembers(m
, group
.getPendingMembers()),
102 resolveJsonMembers(m
, group
.getRequestingMembers()),
103 resolveJsonMembers(m
, group
.getAdminMembers()),
104 groupInviteLink
== null ?
null : groupInviteLink
.getUrl());
105 }).collect(Collectors
.toList());
107 jsonWriter
.write(jsonGroups
);
109 final var writer
= (PlainTextWriter
) outputWriter
;
110 boolean detailed
= ns
.getBoolean("detailed");
111 for (var group
: groups
) {
112 printGroupPlainText(writer
, m
, group
, detailed
);
117 private static final class JsonGroup
{
119 public final String id
;
120 public final String name
;
121 public final String description
;
122 public final boolean isMember
;
123 public final boolean isBlocked
;
124 public final int messageExpirationTime
;
126 public final Set
<JsonGroupMember
> members
;
127 public final Set
<JsonGroupMember
> pendingMembers
;
128 public final Set
<JsonGroupMember
> requestingMembers
;
129 public final Set
<JsonGroupMember
> admins
;
130 public final String groupInviteLink
;
138 final int messageExpirationTime
,
139 Set
<JsonGroupMember
> members
,
140 Set
<JsonGroupMember
> pendingMembers
,
141 Set
<JsonGroupMember
> requestingMembers
,
142 Set
<JsonGroupMember
> admins
,
143 String groupInviteLink
147 this.description
= description
;
148 this.isMember
= isMember
;
149 this.isBlocked
= isBlocked
;
150 this.messageExpirationTime
= messageExpirationTime
;
152 this.members
= members
;
153 this.pendingMembers
= pendingMembers
;
154 this.requestingMembers
= requestingMembers
;
155 this.admins
= admins
;
156 this.groupInviteLink
= groupInviteLink
;
160 private static final class JsonGroupMember
{
162 public final String number
;
163 public final String uuid
;
165 private JsonGroupMember(final String number
, final String uuid
) {
166 this.number
= number
;