From: AsamK Date: Wed, 22 Dec 2021 11:47:42 +0000 (+0100) Subject: Improve exit code for message sending X-Git-Tag: v0.10.1~48 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/9a72733c4f24df7207ec5b0b2dd6d7b8404bc400?ds=sidebyside Improve exit code for message sending Exit with 0 status code if the message was sent successfully to at least one recipient, otherwise exit with status code 2 or 4 (for untrusted). Fixes #828 --- diff --git a/graalvm-config-dir/reflect-config.json b/graalvm-config-dir/reflect-config.json index 2d52a9fa..4d1fd22e 100644 --- a/graalvm-config-dir/reflect-config.json +++ b/graalvm-config-dir/reflect-config.json @@ -300,6 +300,10 @@ "allDeclaredMethods":true, "allDeclaredClasses":true} , +{ + "name":"org.asamk.Signal$Error$UntrustedIdentity", + "methods":[{"name":"","parameterTypes":["java.lang.String"] }]} +, { "name":"org.asamk.Signal$Group", "allDeclaredMethods":true, @@ -458,9 +462,7 @@ "allDeclaredFields":true, "queryAllDeclaredMethods":true, "queryAllDeclaredConstructors":true, - "methods":[ - {"name":"id","parameterTypes":[] } - ]} + "methods":[{"name":"id","parameterTypes":[] }]} , { "name":"org.asamk.signal.json.JsonCallMessage$Hangup", diff --git a/lib/src/main/java/org/asamk/signal/manager/api/SendMessageResults.java b/lib/src/main/java/org/asamk/signal/manager/api/SendMessageResults.java index f0d609e9..5b8cfc03 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/SendMessageResults.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/SendMessageResults.java @@ -3,4 +3,20 @@ package org.asamk.signal.manager.api; import java.util.List; import java.util.Map; -public record SendMessageResults(long timestamp, Map> results) {} +public record SendMessageResults(long timestamp, Map> results) { + + public boolean hasSuccess() { + return results.values() + .stream() + .flatMap(res -> res.stream().map(SendMessageResult::isSuccess)) + .anyMatch(success -> success) || results.values().stream().mapToInt(List::size).sum() == 0; + } + + public boolean hasOnlyUntrustedIdentity() { + return results.values() + .stream() + .flatMap(res -> res.stream().map(SendMessageResult::isIdentityFailure)) + .allMatch(identityFailure -> identityFailure) + && results.values().stream().mapToInt(List::size).sum() > 0; + } +} diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index f2af8a3e..b6f7df0a 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -14,6 +14,7 @@ import org.asamk.signal.manager.api.Message; import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.RecipientIdentifier; import org.asamk.signal.manager.api.SendMessageResult; +import org.asamk.signal.manager.api.SendMessageResults; import org.asamk.signal.manager.api.TypingAction; import org.asamk.signal.manager.api.UpdateGroup; import org.asamk.signal.manager.groups.GroupId; @@ -202,7 +203,7 @@ public class DbusSignalImpl implements Signal { .map(RecipientIdentifier.class::cast) .collect(Collectors.toSet())); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); return results.timestamp(); } catch (AttachmentInvalidException e) { throw new Error.AttachmentInvalid(e.getMessage()); @@ -229,7 +230,7 @@ public class DbusSignalImpl implements Signal { getSingleRecipientIdentifiers(recipients, m.getSelfNumber()).stream() .map(RecipientIdentifier.class::cast) .collect(Collectors.toSet())); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); return results.timestamp(); } catch (IOException e) { throw new Error.Failure(e.getMessage()); @@ -265,7 +266,7 @@ public class DbusSignalImpl implements Signal { getSingleRecipientIdentifiers(recipients, m.getSelfNumber()).stream() .map(RecipientIdentifier.class::cast) .collect(Collectors.toSet())); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); return results.timestamp(); } catch (IOException e) { throw new Error.Failure(e.getMessage()); @@ -283,7 +284,7 @@ public class DbusSignalImpl implements Signal { getSingleRecipientIdentifiers(List.of(recipient), m.getSelfNumber()).stream() .map(RecipientIdentifier.class::cast) .collect(Collectors.toSet())); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); } catch (IOException e) { throw new Error.Failure(e.getMessage()); } catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) { @@ -298,7 +299,7 @@ public class DbusSignalImpl implements Signal { try { final var results = m.sendReadReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), messageIds); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); } catch (IOException e) { throw new Error.Failure(e.getMessage()); } @@ -311,7 +312,7 @@ public class DbusSignalImpl implements Signal { try { final var results = m.sendViewedReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), messageIds); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); } catch (IOException e) { throw new Error.Failure(e.getMessage()); } @@ -342,7 +343,7 @@ public class DbusSignalImpl implements Signal { try { final var results = m.sendMessage(new Message(message, attachments, List.of(), Optional.empty()), Set.of(RecipientIdentifier.NoteToSelf.INSTANCE)); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); return results.timestamp(); } catch (AttachmentInvalidException e) { throw new Error.AttachmentInvalid(e.getMessage()); @@ -357,7 +358,7 @@ public class DbusSignalImpl implements Signal { public void sendEndSessionMessage(final List recipients) { try { final var results = m.sendEndSessionMessage(getSingleRecipientIdentifiers(recipients, m.getSelfNumber())); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); } catch (IOException e) { throw new Error.Failure(e.getMessage()); } @@ -386,7 +387,7 @@ public class DbusSignalImpl implements Signal { try { var results = m.sendMessage(new Message(message, attachments, List.of(), Optional.empty()), Set.of(getGroupRecipientIdentifier(groupId))); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); return results.timestamp(); } catch (IOException e) { throw new Error.Failure(e.getMessage()); @@ -404,7 +405,7 @@ public class DbusSignalImpl implements Signal { try { final var results = m.sendTypingMessage(stop ? TypingAction.STOP : TypingAction.START, Set.of(getGroupRecipientIdentifier(groupId))); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); } catch (IOException e) { throw new Error.Failure(e.getMessage()); } catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) { @@ -419,7 +420,7 @@ public class DbusSignalImpl implements Signal { try { final var results = m.sendRemoteDeleteMessage(targetSentTimestamp, Set.of(getGroupRecipientIdentifier(groupId))); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); return results.timestamp(); } catch (IOException e) { throw new Error.Failure(e.getMessage()); @@ -442,7 +443,7 @@ public class DbusSignalImpl implements Signal { getSingleRecipientIdentifier(targetAuthor, m.getSelfNumber()), targetSentTimestamp, Set.of(getGroupRecipientIdentifier(groupId))); - checkSendMessageResults(results.timestamp(), results.results()); + checkSendMessageResults(results); return results.timestamp(); } catch (IOException e) { throw new Error.Failure(e.getMessage()); @@ -563,7 +564,7 @@ public class DbusSignalImpl implements Signal { if (groupId == null) { final var results = m.createGroup(name, memberIdentifiers, avatar == null ? null : new File(avatar)); updateGroups(); - checkSendMessageResults(results.second().timestamp(), results.second().results()); + checkGroupSendMessageResults(results.second().timestamp(), results.second().results()); return results.first().serialize(); } else { final var results = m.updateGroup(getGroupId(groupId), @@ -573,7 +574,7 @@ public class DbusSignalImpl implements Signal { .withAvatarFile(avatar == null ? null : new File(avatar)) .build()); if (results != null) { - checkSendMessageResults(results.timestamp(), results.results()); + checkGroupSendMessageResults(results.timestamp(), results.results()); } return groupId; } @@ -790,7 +791,7 @@ public class DbusSignalImpl implements Signal { return; } - final var message = timestamp + "\nFailed to send message:\n" + error + '\n'; + final var message = "\nFailed to send message:\n" + error + '\n' + timestamp; if (result.isIdentityFailure()) { throw new Error.UntrustedIdentity(message); @@ -799,31 +800,29 @@ public class DbusSignalImpl implements Signal { } } - private static void checkSendMessageResults( - long timestamp, Map> results - ) throws DBusExecutionException { - final var sendMessageResults = results.values().stream().findFirst(); - if (results.size() == 1 && sendMessageResults.get().size() == 1) { - checkSendMessageResult(timestamp, sendMessageResults.get().stream().findFirst().get()); + private void checkSendMessageResults(final SendMessageResults results) { + final var sendMessageResults = results.results().values().stream().findFirst(); + if (results.results().size() == 1 && sendMessageResults.get().size() == 1) { + checkSendMessageResult(results.timestamp(), sendMessageResults.get().stream().findFirst().get()); return; } - var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results); - if (errors.size() == 0) { + if (results.hasSuccess()) { return; } var message = new StringBuilder(); - message.append(timestamp).append('\n'); - message.append("Failed to send (some) messages:\n"); + message.append("Failed to send messages:\n"); + var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results.results()); for (var error : errors) { message.append(error).append('\n'); } + message.append(results.timestamp()); throw new Error.Failure(message.toString()); } - private static void checkSendMessageResults( + private static void checkGroupSendMessageResults( long timestamp, Collection results ) throws DBusExecutionException { if (results.size() == 1) { @@ -832,16 +831,16 @@ public class DbusSignalImpl implements Signal { } var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results); - if (errors.size() == 0) { + if (errors.size() < results.size()) { return; } var message = new StringBuilder(); - message.append(timestamp).append('\n'); - message.append("Failed to send (some) messages:\n"); + message.append("Failed to send message:\n"); for (var error : errors) { message.append(error).append('\n'); } + message.append(timestamp); throw new Error.Failure(message.toString()); } diff --git a/src/main/java/org/asamk/signal/util/SendMessageResultUtils.java b/src/main/java/org/asamk/signal/util/SendMessageResultUtils.java index bb46a89d..74f49534 100644 --- a/src/main/java/org/asamk/signal/util/SendMessageResultUtils.java +++ b/src/main/java/org/asamk/signal/util/SendMessageResultUtils.java @@ -1,5 +1,8 @@ package org.asamk.signal.util; +import org.asamk.signal.commands.exceptions.CommandException; +import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException; +import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.json.JsonSendMessageResult; import org.asamk.signal.manager.api.ProofRequiredException; import org.asamk.signal.manager.api.RecipientIdentifier; @@ -33,7 +36,9 @@ public class SendMessageResultUtils { } } - public static void outputResult(final OutputWriter outputWriter, final SendMessageResults sendMessageResults) { + public static void outputResult( + final OutputWriter outputWriter, final SendMessageResults sendMessageResults + ) throws CommandException { if (outputWriter instanceof PlainTextWriter writer) { var errors = getErrorMessagesFromSendMessageResults(sendMessageResults.results()); printSendMessageResultErrors(writer, errors); @@ -43,6 +48,13 @@ public class SendMessageResultUtils { var results = getJsonSendMessageResults(sendMessageResults.results()); writer.write(Map.of("timestamp", sendMessageResults.timestamp(), "results", results)); } + if (!sendMessageResults.hasSuccess()) { + if (sendMessageResults.hasOnlyUntrustedIdentity()) { + throw new UntrustedKeyErrorException("Failed to send message due to untrusted identities"); + } else { + throw new UserErrorException("Failed to send message"); + } + } } public static List getErrorMessagesFromSendMessageResults(final Map> mapResults) { @@ -106,7 +118,7 @@ public class SendMessageResultUtils { } } - public static List getJsonSendMessageResults(final Map> mapResults) { + private static List getJsonSendMessageResults(final Map> mapResults) { return mapResults.entrySet().stream().flatMap(entry -> { final var groupId = entry.getKey() instanceof RecipientIdentifier.Group g ? g.groupId() : null; return entry.getValue().stream().map(r -> JsonSendMessageResult.from(r, groupId));