]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java
Implement jsonRpc command
[signal-cli] / src / main / java / org / asamk / signal / commands / UpdateGroupCommand.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;
8 import org.asamk.signal.GroupLinkState;
9 import org.asamk.signal.GroupPermission;
10 import org.asamk.signal.OutputWriter;
11 import org.asamk.signal.PlainTextWriter;
12 import org.asamk.signal.commands.exceptions.CommandException;
13 import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
14 import org.asamk.signal.commands.exceptions.UserErrorException;
15 import org.asamk.signal.manager.AttachmentInvalidException;
16 import org.asamk.signal.manager.Manager;
17 import org.asamk.signal.manager.groups.GroupId;
18 import org.asamk.signal.manager.groups.GroupIdFormatException;
19 import org.asamk.signal.manager.groups.GroupNotFoundException;
20 import org.asamk.signal.manager.groups.NotAGroupMemberException;
21 import org.asamk.signal.util.ErrorUtils;
22 import org.asamk.signal.util.Util;
23 import org.freedesktop.dbus.exceptions.DBusExecutionException;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26 import org.whispersystems.signalservice.api.util.InvalidNumberException;
27
28 import java.io.File;
29 import java.io.IOException;
30 import java.util.ArrayList;
31 import java.util.Base64;
32 import java.util.List;
33
34 public class UpdateGroupCommand implements DbusCommand, LocalCommand {
35
36 private final static Logger logger = LoggerFactory.getLogger(UpdateGroupCommand.class);
37 private final OutputWriter outputWriter;
38
39 public UpdateGroupCommand(final OutputWriter outputWriter) {
40 this.outputWriter = outputWriter;
41 }
42
43 public static void attachToSubparser(final Subparser subparser) {
44 subparser.help("Create or update a group.");
45 subparser.addArgument("-g", "--group-id", "--group").help("Specify the group ID.");
46 subparser.addArgument("-n", "--name").help("Specify the new group name.");
47 subparser.addArgument("-d", "--description").help("Specify the new group description.");
48 subparser.addArgument("-a", "--avatar").help("Specify a new group avatar image file");
49 subparser.addArgument("-m", "--member").nargs("*").help("Specify one or more members to add to the group");
50 subparser.addArgument("-r", "--remove-member")
51 .nargs("*")
52 .help("Specify one or more members to remove from the group");
53 subparser.addArgument("--admin").nargs("*").help("Specify one or more members to make a group admin");
54 subparser.addArgument("--remove-admin")
55 .nargs("*")
56 .help("Specify one or more members to remove group admin privileges");
57
58 subparser.addArgument("--reset-link")
59 .action(Arguments.storeTrue())
60 .help("Reset group link and create new link password");
61 subparser.addArgument("--link")
62 .help("Set group link state, with or without admin approval")
63 .type(Arguments.enumStringType(GroupLinkState.class));
64
65 subparser.addArgument("--set-permission-add-member")
66 .help("Set permission to add new group members")
67 .type(Arguments.enumStringType(GroupPermission.class));
68 subparser.addArgument("--set-permission-edit-details")
69 .help("Set permission to edit group details")
70 .type(Arguments.enumStringType(GroupPermission.class));
71
72 subparser.addArgument("-e", "--expiration").type(int.class).help("Set expiration time of messages (seconds)");
73 }
74
75 @Override
76 public void handleCommand(final Namespace ns, final Manager m) throws CommandException {
77 final var writer = (PlainTextWriter) outputWriter;
78 GroupId groupId = null;
79 final var groupIdString = ns.getString("group-id");
80 if (groupIdString != null) {
81 try {
82 groupId = Util.decodeGroupId(groupIdString);
83 } catch (GroupIdFormatException e) {
84 throw new UserErrorException("Invalid group id: " + e.getMessage());
85 }
86 }
87
88 var groupName = ns.getString("name");
89 var groupDescription = ns.getString("description");
90 var groupMembers = ns.<String>getList("member");
91 var groupRemoveMembers = ns.<String>getList("remove-member");
92 var groupAdmins = ns.<String>getList("admin");
93 var groupRemoveAdmins = ns.<String>getList("remove-admin");
94 var groupAvatar = ns.getString("avatar");
95 var groupResetLink = ns.getBoolean("reset-link");
96 var groupLinkState = ns.<GroupLinkState>get("link");
97 var groupExpiration = ns.getInt("expiration");
98 var groupAddMemberPermission = ns.<GroupPermission>get("set-permission-add-member");
99 var groupEditDetailsPermission = ns.<GroupPermission>get("set-permission-edit-details");
100
101 try {
102 if (groupId == null) {
103 var results = m.createGroup(groupName,
104 groupMembers,
105 groupAvatar == null ? null : new File(groupAvatar));
106 ErrorUtils.handleTimestampAndSendMessageResults(writer, 0, results.second());
107 groupId = results.first();
108 writer.println("Created new group: \"{}\"", groupId.toBase64());
109 groupName = null;
110 groupMembers = null;
111 groupAvatar = null;
112 }
113
114 var results = m.updateGroup(groupId,
115 groupName,
116 groupDescription,
117 groupMembers,
118 groupRemoveMembers,
119 groupAdmins,
120 groupRemoveAdmins,
121 groupResetLink,
122 groupLinkState != null ? groupLinkState.toLinkState() : null,
123 groupAddMemberPermission != null ? groupAddMemberPermission.toManager() : null,
124 groupEditDetailsPermission != null ? groupEditDetailsPermission.toManager() : null,
125 groupAvatar == null ? null : new File(groupAvatar),
126 groupExpiration);
127 if (results != null) {
128 ErrorUtils.handleTimestampAndSendMessageResults(writer, results.first(), results.second());
129 }
130 } catch (AttachmentInvalidException e) {
131 throw new UserErrorException("Failed to add avatar attachment for group\": " + e.getMessage());
132 } catch (GroupNotFoundException e) {
133 logger.warn("Unknown group id: {}", groupIdString);
134 } catch (NotAGroupMemberException e) {
135 logger.warn("You're not a group member");
136 } catch (InvalidNumberException e) {
137 throw new UserErrorException("Failed to parse member number: " + e.getMessage());
138 } catch (IOException e) {
139 throw new UnexpectedErrorException("Failed to send message: " + e.getMessage());
140 }
141 }
142
143 @Override
144 public void handleCommand(final Namespace ns, final Signal signal) throws CommandException {
145 final var writer = (PlainTextWriter) outputWriter;
146 byte[] groupId = null;
147 if (ns.getString("group-id") != null) {
148 try {
149 groupId = Util.decodeGroupId(ns.getString("group-id")).serialize();
150 } catch (GroupIdFormatException e) {
151 throw new UserErrorException("Invalid group id: " + e.getMessage());
152 }
153 }
154 if (groupId == null) {
155 groupId = new byte[0];
156 }
157
158 var groupName = ns.getString("name");
159 if (groupName == null) {
160 groupName = "";
161 }
162
163 List<String> groupMembers = ns.getList("member");
164 if (groupMembers == null) {
165 groupMembers = new ArrayList<>();
166 }
167
168 var groupAvatar = ns.getString("avatar");
169 if (groupAvatar == null) {
170 groupAvatar = "";
171 }
172
173 try {
174 var newGroupId = signal.updateGroup(groupId, groupName, groupMembers, groupAvatar);
175 if (groupId.length != newGroupId.length) {
176 writer.println("Created new group: \"{}\"", Base64.getEncoder().encodeToString(newGroupId));
177 }
178 } catch (Signal.Error.AttachmentInvalid e) {
179 throw new UserErrorException("Failed to add avatar attachment for group\": " + e.getMessage());
180 } catch (DBusExecutionException e) {
181 throw new UnexpectedErrorException("Failed to send message: " + e.getMessage());
182 }
183 }
184 }