]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/commands/ListGroupsCommand.java
Prevent non-admins from sending to announcement groups
[signal-cli] / src / main / java / org / asamk / signal / commands / ListGroupsCommand.java
1 package org.asamk.signal.commands;
2
3 import net.sourceforge.argparse4j.impl.Arguments;
4 import net.sourceforge.argparse4j.inf.Namespace;
5 import net.sourceforge.argparse4j.inf.Subparser;
6
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;
17
18 import java.util.Set;
19 import java.util.UUID;
20 import java.util.stream.Collectors;
21
22 public class ListGroupsCommand implements JsonRpcLocalCommand {
23
24 private final static Logger logger = LoggerFactory.getLogger(ListGroupsCommand.class);
25
26 @Override
27 public String getName() {
28 return "listGroups";
29 }
30
31 @Override
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");
37 }
38
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());
44 }
45
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());
52 }
53
54 private static void printGroupPlainText(
55 PlainTextWriter writer, Manager m, GroupInfo group, boolean detailed
56 ) {
57 if (detailed) {
58 final var groupInviteLink = group.getGroupInviteLink();
59
60 writer.println(
61 "Id: {} Name: {} Description: {} Active: {} Blocked: {} Members: {} Pending members: {} Requesting members: {} Admins: {} Message expiration: {} Link: {}",
62 group.getGroupId().toBase64(),
63 group.getTitle(),
64 group.getDescription(),
65 group.isMember(m.getSelfRecipientId()),
66 group.isBlocked(),
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());
73 } else {
74 writer.println("Id: {} Name: {} Active: {} Blocked: {}",
75 group.getGroupId().toBase64(),
76 group.getTitle(),
77 group.isMember(m.getSelfRecipientId()),
78 group.isBlocked());
79 }
80 }
81
82 @Override
83 public void handleCommand(
84 final Namespace ns, final Manager m, final OutputWriter outputWriter
85 ) throws CommandException {
86 final var groups = m.getGroups();
87
88 if (outputWriter instanceof JsonWriter) {
89 final var jsonWriter = (JsonWriter) outputWriter;
90
91 var jsonGroups = groups.stream().map(group -> {
92 final var groupInviteLink = group.getGroupInviteLink();
93
94 return new JsonGroup(group.getGroupId().toBase64(),
95 group.getTitle(),
96 group.getDescription(),
97 group.isMember(m.getSelfRecipientId()),
98 group.isBlocked(),
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());
106
107 jsonWriter.write(jsonGroups);
108 } else {
109 final var writer = (PlainTextWriter) outputWriter;
110 boolean detailed = ns.getBoolean("detailed");
111 for (var group : groups) {
112 printGroupPlainText(writer, m, group, detailed);
113 }
114 }
115 }
116
117 private static final class JsonGroup {
118
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;
125
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;
131
132 public JsonGroup(
133 String id,
134 String name,
135 String description,
136 boolean isMember,
137 boolean isBlocked,
138 final int messageExpirationTime,
139 Set<JsonGroupMember> members,
140 Set<JsonGroupMember> pendingMembers,
141 Set<JsonGroupMember> requestingMembers,
142 Set<JsonGroupMember> admins,
143 String groupInviteLink
144 ) {
145 this.id = id;
146 this.name = name;
147 this.description = description;
148 this.isMember = isMember;
149 this.isBlocked = isBlocked;
150 this.messageExpirationTime = messageExpirationTime;
151
152 this.members = members;
153 this.pendingMembers = pendingMembers;
154 this.requestingMembers = requestingMembers;
155 this.admins = admins;
156 this.groupInviteLink = groupInviteLink;
157 }
158 }
159
160 private static final class JsonGroupMember {
161
162 public final String number;
163 public final String uuid;
164
165 private JsonGroupMember(final String number, final String uuid) {
166 this.number = number;
167 this.uuid = uuid;
168 }
169 }
170 }