]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java
Add CommandException to abstract cli return codes for errors
[signal-cli] / src / main / java / org / asamk / signal / dbus / DbusSignalImpl.java
1 package org.asamk.signal.dbus;
2
3 import org.asamk.Signal;
4 import org.asamk.signal.manager.AttachmentInvalidException;
5 import org.asamk.signal.manager.Manager;
6 import org.asamk.signal.manager.groups.GroupId;
7 import org.asamk.signal.manager.groups.GroupNotFoundException;
8 import org.asamk.signal.manager.groups.NotAGroupMemberException;
9 import org.asamk.signal.util.ErrorUtils;
10 import org.freedesktop.dbus.exceptions.DBusExecutionException;
11 import org.whispersystems.libsignal.util.guava.Optional;
12 import org.whispersystems.signalservice.api.messages.SendMessageResult;
13 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
14 import org.whispersystems.signalservice.api.util.InvalidNumberException;
15
16 import java.io.File;
17 import java.io.IOException;
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.stream.Collectors;
21
22 public class DbusSignalImpl implements Signal {
23
24 private final Manager m;
25
26 public DbusSignalImpl(final Manager m) {
27 this.m = m;
28 }
29
30 @Override
31 public boolean isRemote() {
32 return false;
33 }
34
35 @Override
36 public String getObjectPath() {
37 return null;
38 }
39
40 @Override
41 public long sendMessage(final String message, final List<String> attachments, final String recipient) {
42 var recipients = new ArrayList<String>(1);
43 recipients.add(recipient);
44 return sendMessage(message, attachments, recipients);
45 }
46
47 private static void checkSendMessageResult(long timestamp, SendMessageResult result) throws DBusExecutionException {
48 var error = ErrorUtils.getErrorMessageFromSendMessageResult(result);
49
50 if (error == null) {
51 return;
52 }
53
54 final var message = timestamp + "\nFailed to send message:\n" + error + '\n';
55
56 if (result.getIdentityFailure() != null) {
57 throw new Error.UntrustedIdentity(message);
58 } else {
59 throw new Error.Failure(message);
60 }
61 }
62
63 private static void checkSendMessageResults(
64 long timestamp, List<SendMessageResult> results
65 ) throws DBusExecutionException {
66 if (results.size() == 1) {
67 checkSendMessageResult(timestamp, results.get(0));
68 return;
69 }
70
71 var errors = ErrorUtils.getErrorMessagesFromSendMessageResults(results);
72 if (errors.size() == 0) {
73 return;
74 }
75
76 var message = new StringBuilder();
77 message.append(timestamp).append('\n');
78 message.append("Failed to send (some) messages:\n");
79 for (var error : errors) {
80 message.append(error).append('\n');
81 }
82
83 throw new Error.Failure(message.toString());
84 }
85
86 @Override
87 public long sendMessage(final String message, final List<String> attachments, final List<String> recipients) {
88 try {
89 final var results = m.sendMessage(message, attachments, recipients);
90 checkSendMessageResults(results.first(), results.second());
91 return results.first();
92 } catch (InvalidNumberException e) {
93 throw new Error.InvalidNumber(e.getMessage());
94 } catch (AttachmentInvalidException e) {
95 throw new Error.AttachmentInvalid(e.getMessage());
96 } catch (IOException e) {
97 throw new Error.Failure(e.getMessage());
98 }
99 }
100
101 @Override
102 public long sendNoteToSelfMessage(
103 final String message, final List<String> attachments
104 ) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity {
105 try {
106 final var results = m.sendSelfMessage(message, attachments);
107 checkSendMessageResult(results.first(), results.second());
108 return results.first();
109 } catch (AttachmentInvalidException e) {
110 throw new Error.AttachmentInvalid(e.getMessage());
111 } catch (IOException e) {
112 throw new Error.Failure(e.getMessage());
113 }
114 }
115
116 @Override
117 public void sendEndSessionMessage(final List<String> recipients) {
118 try {
119 final var results = m.sendEndSessionMessage(recipients);
120 checkSendMessageResults(results.first(), results.second());
121 } catch (IOException e) {
122 throw new Error.Failure(e.getMessage());
123 } catch (InvalidNumberException e) {
124 throw new Error.InvalidNumber(e.getMessage());
125 }
126 }
127
128 @Override
129 public long sendGroupMessage(final String message, final List<String> attachments, final byte[] groupId) {
130 try {
131 var results = m.sendGroupMessage(message, attachments, GroupId.unknownVersion(groupId));
132 checkSendMessageResults(results.first(), results.second());
133 return results.first();
134 } catch (IOException e) {
135 throw new Error.Failure(e.getMessage());
136 } catch (GroupNotFoundException | NotAGroupMemberException e) {
137 throw new Error.GroupNotFound(e.getMessage());
138 } catch (AttachmentInvalidException e) {
139 throw new Error.AttachmentInvalid(e.getMessage());
140 }
141 }
142
143 @Override
144 public String getContactName(final String number) {
145 try {
146 return m.getContactName(number);
147 } catch (InvalidNumberException e) {
148 throw new Error.InvalidNumber(e.getMessage());
149 }
150 }
151
152 @Override
153 public void setContactName(final String number, final String name) {
154 try {
155 m.setContactName(number, name);
156 } catch (InvalidNumberException e) {
157 throw new Error.InvalidNumber(e.getMessage());
158 }
159 }
160
161 @Override
162 public void setContactBlocked(final String number, final boolean blocked) {
163 try {
164 m.setContactBlocked(number, blocked);
165 } catch (InvalidNumberException e) {
166 throw new Error.InvalidNumber(e.getMessage());
167 }
168 }
169
170 @Override
171 public void setGroupBlocked(final byte[] groupId, final boolean blocked) {
172 try {
173 m.setGroupBlocked(GroupId.unknownVersion(groupId), blocked);
174 } catch (GroupNotFoundException e) {
175 throw new Error.GroupNotFound(e.getMessage());
176 }
177 }
178
179 @Override
180 public List<byte[]> getGroupIds() {
181 var groups = m.getGroups();
182 var ids = new ArrayList<byte[]>(groups.size());
183 for (var group : groups) {
184 ids.add(group.getGroupId().serialize());
185 }
186 return ids;
187 }
188
189 @Override
190 public String getGroupName(final byte[] groupId) {
191 var group = m.getGroup(GroupId.unknownVersion(groupId));
192 if (group == null) {
193 return "";
194 } else {
195 return group.getTitle();
196 }
197 }
198
199 @Override
200 public List<String> getGroupMembers(final byte[] groupId) {
201 var group = m.getGroup(GroupId.unknownVersion(groupId));
202 if (group == null) {
203 return List.of();
204 } else {
205 return group.getMembers()
206 .stream()
207 .map(m::resolveSignalServiceAddress)
208 .map(SignalServiceAddress::getLegacyIdentifier)
209 .collect(Collectors.toList());
210 }
211 }
212
213 @Override
214 public byte[] updateGroup(byte[] groupId, String name, List<String> members, String avatar) {
215 try {
216 if (groupId.length == 0) {
217 groupId = null;
218 }
219 if (name.isEmpty()) {
220 name = null;
221 }
222 if (members.isEmpty()) {
223 members = null;
224 }
225 if (avatar.isEmpty()) {
226 avatar = null;
227 }
228 final var results = m.updateGroup(groupId == null ? null : GroupId.unknownVersion(groupId),
229 name,
230 members,
231 avatar == null ? null : new File(avatar));
232 checkSendMessageResults(0, results.second());
233 return results.first().serialize();
234 } catch (IOException e) {
235 throw new Error.Failure(e.getMessage());
236 } catch (GroupNotFoundException | NotAGroupMemberException e) {
237 throw new Error.GroupNotFound(e.getMessage());
238 } catch (InvalidNumberException e) {
239 throw new Error.InvalidNumber(e.getMessage());
240 } catch (AttachmentInvalidException e) {
241 throw new Error.AttachmentInvalid(e.getMessage());
242 }
243 }
244
245 @Override
246 public boolean isRegistered() {
247 return true;
248 }
249
250 @Override
251 public void updateProfile(
252 final String name,
253 final String about,
254 final String aboutEmoji,
255 String avatarPath,
256 final boolean removeAvatar
257 ) {
258 try {
259 if (avatarPath.isEmpty()) {
260 avatarPath = null;
261 }
262 Optional<File> avatarFile = removeAvatar
263 ? Optional.absent()
264 : avatarPath == null ? null : Optional.of(new File(avatarPath));
265 m.setProfile(name, about, aboutEmoji, avatarFile);
266 } catch (IOException e) {
267 throw new Error.Failure(e.getMessage());
268 }
269 }
270
271 }