From 06e93b84da2718c31111e820cd35a3354f22bae2 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sat, 11 Dec 2021 12:44:11 +0100 Subject: [PATCH] Handle send failures as non fatal and return detailed results in json output Fixes #348 --- graalvm-config-dir/reflect-config.json | 28 ++++++++ .../signal/commands/JoinGroupCommand.java | 24 +++++-- .../signal/commands/QuitGroupCommand.java | 18 +---- .../signal/commands/RemoteDeleteCommand.java | 18 +---- .../asamk/signal/commands/SendCommand.java | 21 ++---- .../signal/commands/SendReactionCommand.java | 18 +---- .../signal/commands/SendReceiptCommand.java | 18 +---- .../signal/commands/SendTypingCommand.java | 18 +---- .../signal/commands/UpdateGroupCommand.java | 43 +++++++----- .../org/asamk/signal/dbus/DbusSignalImpl.java | 8 +-- .../signal/json/JsonRecipientAddress.java | 12 ++++ .../signal/json/JsonSendMessageResult.java | 38 +++++++++++ ...Utils.java => SendMessageResultUtils.java} | 65 +++++++++++++------ 13 files changed, 191 insertions(+), 138 deletions(-) create mode 100644 src/main/java/org/asamk/signal/json/JsonRecipientAddress.java create mode 100644 src/main/java/org/asamk/signal/json/JsonSendMessageResult.java rename src/main/java/org/asamk/signal/util/{ErrorUtils.java => SendMessageResultUtils.java} (53%) diff --git a/graalvm-config-dir/reflect-config.json b/graalvm-config-dir/reflect-config.json index a6d83165..cb75cbd9 100644 --- a/graalvm-config-dir/reflect-config.json +++ b/graalvm-config-dir/reflect-config.json @@ -578,12 +578,40 @@ "allDeclaredMethods":true, "allDeclaredConstructors":true} , +{ + "name":"org.asamk.signal.json.JsonRecipientAddress", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[ + {"name":"number","parameterTypes":[] }, + {"name":"uuid","parameterTypes":[] } + ]} +, { "name":"org.asamk.signal.json.JsonRemoteDelete", "allDeclaredFields":true, "allDeclaredMethods":true, "allDeclaredConstructors":true} , +{ + "name":"org.asamk.signal.json.JsonSendMessageResult", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[ + {"name":"groupId","parameterTypes":[] }, + {"name":"recipientAddress","parameterTypes":[] }, + {"name":"retryAfterSeconds","parameterTypes":[] }, + {"name":"token","parameterTypes":[] }, + {"name":"type","parameterTypes":[] } + ]} +, +{ + "name":"org.asamk.signal.json.JsonSendMessageResult$Type", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true} +, { "name":"org.asamk.signal.json.JsonSharedContact", "allDeclaredFields":true, diff --git a/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java b/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java index e04fca06..31fc4caf 100644 --- a/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/JoinGroupCommand.java @@ -13,13 +13,12 @@ import org.asamk.signal.manager.groups.GroupInviteLinkUrl; import org.asamk.signal.output.JsonWriter; import org.asamk.signal.output.OutputWriter; import org.asamk.signal.output.PlainTextWriter; +import org.asamk.signal.util.SendMessageResultUtils; import org.freedesktop.dbus.exceptions.DBusExecutionException; import java.io.IOException; import java.util.Map; -import static org.asamk.signal.util.ErrorUtils.handleSendMessageResults; - public class JoinGroupCommand implements JsonRpcLocalCommand { @Override @@ -55,10 +54,23 @@ public class JoinGroupCommand implements JsonRpcLocalCommand { final var results = m.joinGroup(linkUrl); var newGroupId = results.first(); if (outputWriter instanceof JsonWriter writer) { + var jsonResults = SendMessageResultUtils.getJsonSendMessageResults(results.second().results()); if (!m.getGroup(newGroupId).isMember()) { - writer.write(Map.of("groupId", newGroupId.toBase64(), "onlyRequested", true)); + writer.write(Map.of("timestamp", + results.second().timestamp(), + "results", + jsonResults, + "groupId", + newGroupId.toBase64(), + "onlyRequested", + true)); } else { - writer.write(Map.of("groupId", newGroupId.toBase64())); + writer.write(Map.of("timestamp", + results.second().timestamp(), + "results", + jsonResults, + "groupId", + newGroupId.toBase64())); } } else { final var writer = (PlainTextWriter) outputWriter; @@ -67,8 +79,10 @@ public class JoinGroupCommand implements JsonRpcLocalCommand { } else { writer.println("Joined group \"{}\"", newGroupId.toBase64()); } + var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results.second().results()); + SendMessageResultUtils.printSendMessageResultErrors(writer, errors); + writer.println("{}", results.second().timestamp()); } - handleSendMessageResults(results.second().results()); } catch (IOException e) { throw new IOErrorException("Failed to send message: " + e.getMessage() diff --git a/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java b/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java index 801a2640..6266a603 100644 --- a/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/QuitGroupCommand.java @@ -11,17 +11,14 @@ import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.LastGroupAdminException; import org.asamk.signal.manager.groups.NotAGroupMemberException; -import org.asamk.signal.output.JsonWriter; import org.asamk.signal.output.OutputWriter; -import org.asamk.signal.output.PlainTextWriter; import org.asamk.signal.util.CommandUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.util.Map; -import static org.asamk.signal.util.ErrorUtils.handleSendMessageResults; +import static org.asamk.signal.util.SendMessageResultUtils.outputResult; public class QuitGroupCommand implements JsonRpcLocalCommand { @@ -55,9 +52,7 @@ public class QuitGroupCommand implements JsonRpcLocalCommand { try { try { final var results = m.quitGroup(groupId, groupAdmins); - final var timestamp = results.timestamp(); - outputResult(outputWriter, timestamp); - handleSendMessageResults(results.results()); + outputResult(outputWriter, results); } catch (NotAGroupMemberException e) { logger.info("User is not a group member"); } @@ -77,13 +72,4 @@ public class QuitGroupCommand implements JsonRpcLocalCommand { throw new UserErrorException("You need to specify a new admin with --admin: " + e.getMessage()); } } - - private void outputResult(final OutputWriter outputWriter, final long timestamp) { - if (outputWriter instanceof PlainTextWriter writer) { - writer.println("{}", timestamp); - } else { - final var writer = (JsonWriter) outputWriter; - writer.write(Map.of("timestamp", timestamp)); - } - } } diff --git a/src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java b/src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java index 54a8d6fb..85d2dcd4 100644 --- a/src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java +++ b/src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java @@ -11,14 +11,12 @@ import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.GroupSendingNotAllowedException; import org.asamk.signal.manager.groups.NotAGroupMemberException; -import org.asamk.signal.output.JsonWriter; import org.asamk.signal.output.OutputWriter; -import org.asamk.signal.output.PlainTextWriter; import org.asamk.signal.util.CommandUtil; -import org.asamk.signal.util.ErrorUtils; import java.io.IOException; -import java.util.Map; + +import static org.asamk.signal.util.SendMessageResultUtils.outputResult; public class RemoteDeleteCommand implements JsonRpcLocalCommand { @@ -56,8 +54,7 @@ public class RemoteDeleteCommand implements JsonRpcLocalCommand { try { final var results = m.sendRemoteDeleteMessage(targetTimestamp, recipientIdentifiers); - outputResult(outputWriter, results.timestamp()); - ErrorUtils.handleSendMessageResults(results.results()); + outputResult(outputWriter, results); } catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) { throw new UserErrorException(e.getMessage()); } catch (IOException e) { @@ -65,13 +62,4 @@ public class RemoteDeleteCommand implements JsonRpcLocalCommand { .getSimpleName() + ")", e); } } - - private void outputResult(final OutputWriter outputWriter, final long timestamp) { - if (outputWriter instanceof PlainTextWriter writer) { - writer.println("{}", timestamp); - } else { - final var writer = (JsonWriter) outputWriter; - writer.write(Map.of("timestamp", timestamp)); - } - } } diff --git a/src/main/java/org/asamk/signal/commands/SendCommand.java b/src/main/java/org/asamk/signal/commands/SendCommand.java index 1af21d53..08f2d9a3 100644 --- a/src/main/java/org/asamk/signal/commands/SendCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendCommand.java @@ -14,11 +14,8 @@ import org.asamk.signal.manager.api.RecipientIdentifier; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.GroupSendingNotAllowedException; import org.asamk.signal.manager.groups.NotAGroupMemberException; -import org.asamk.signal.output.JsonWriter; import org.asamk.signal.output.OutputWriter; -import org.asamk.signal.output.PlainTextWriter; import org.asamk.signal.util.CommandUtil; -import org.asamk.signal.util.ErrorUtils; import org.asamk.signal.util.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,11 +24,12 @@ import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.asamk.signal.util.SendMessageResultUtils.outputResult; + public class SendCommand implements JsonRpcLocalCommand { private final static Logger logger = LoggerFactory.getLogger(SendCommand.class); @@ -93,8 +91,7 @@ public class SendCommand implements JsonRpcLocalCommand { try { final var results = m.sendEndSessionMessage(singleRecipients); - outputResult(outputWriter, results.timestamp()); - ErrorUtils.handleSendMessageResults(results.results()); + outputResult(outputWriter, results); return; } catch (IOException e) { throw new UnexpectedErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass() @@ -140,8 +137,7 @@ public class SendCommand implements JsonRpcLocalCommand { try { var results = m.sendMessage(new Message(messageText, attachments, mentions, Optional.ofNullable(quote)), recipientIdentifiers); - outputResult(outputWriter, results.timestamp()); - ErrorUtils.handleSendMessageResults(results.results()); + outputResult(outputWriter, results); } catch (AttachmentInvalidException | IOException e) { throw new UnexpectedErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass() .getSimpleName() + ")", e); @@ -168,13 +164,4 @@ public class SendCommand implements JsonRpcLocalCommand { } return mentions; } - - private void outputResult(final OutputWriter outputWriter, final long timestamp) { - if (outputWriter instanceof PlainTextWriter writer) { - writer.println("{}", timestamp); - } else { - final var writer = (JsonWriter) outputWriter; - writer.write(Map.of("timestamp", timestamp)); - } - } } diff --git a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java index d6275726..e445a991 100644 --- a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java @@ -11,14 +11,12 @@ import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.GroupSendingNotAllowedException; import org.asamk.signal.manager.groups.NotAGroupMemberException; -import org.asamk.signal.output.JsonWriter; import org.asamk.signal.output.OutputWriter; -import org.asamk.signal.output.PlainTextWriter; import org.asamk.signal.util.CommandUtil; -import org.asamk.signal.util.ErrorUtils; import java.io.IOException; -import java.util.Map; + +import static org.asamk.signal.util.SendMessageResultUtils.outputResult; public class SendReactionCommand implements JsonRpcLocalCommand { @@ -72,8 +70,7 @@ public class SendReactionCommand implements JsonRpcLocalCommand { CommandUtil.getSingleRecipientIdentifier(targetAuthor, m.getSelfNumber()), targetTimestamp, recipientIdentifiers); - outputResult(outputWriter, results.timestamp()); - ErrorUtils.handleSendMessageResults(results.results()); + outputResult(outputWriter, results); } catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) { throw new UserErrorException(e.getMessage()); } catch (IOException e) { @@ -81,13 +78,4 @@ public class SendReactionCommand implements JsonRpcLocalCommand { .getSimpleName() + ")", e); } } - - private void outputResult(final OutputWriter outputWriter, final long timestamp) { - if (outputWriter instanceof PlainTextWriter writer) { - writer.println("{}", timestamp); - } else { - final var writer = (JsonWriter) outputWriter; - writer.write(Map.of("timestamp", timestamp)); - } - } } diff --git a/src/main/java/org/asamk/signal/commands/SendReceiptCommand.java b/src/main/java/org/asamk/signal/commands/SendReceiptCommand.java index bc2ef379..6ba8a40c 100644 --- a/src/main/java/org/asamk/signal/commands/SendReceiptCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendReceiptCommand.java @@ -7,14 +7,12 @@ import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.api.SendMessageResults; -import org.asamk.signal.output.JsonWriter; import org.asamk.signal.output.OutputWriter; -import org.asamk.signal.output.PlainTextWriter; import org.asamk.signal.util.CommandUtil; -import org.asamk.signal.util.ErrorUtils; import java.io.IOException; -import java.util.Map; + +import static org.asamk.signal.util.SendMessageResultUtils.outputResult; public class SendReceiptCommand implements JsonRpcLocalCommand { @@ -55,20 +53,10 @@ public class SendReceiptCommand implements JsonRpcLocalCommand { } else { throw new UserErrorException("Unknown receipt type: " + type); } - outputResult(outputWriter, results.timestamp()); - ErrorUtils.handleSendMessageResults(results.results()); + outputResult(outputWriter, results); } catch (IOException e) { throw new UserErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass() .getSimpleName() + ")"); } } - - private void outputResult(final OutputWriter outputWriter, final long timestamp) { - if (outputWriter instanceof PlainTextWriter writer) { - writer.println("{}", timestamp); - } else { - final var writer = (JsonWriter) outputWriter; - writer.write(Map.of("timestamp", timestamp)); - } - } } diff --git a/src/main/java/org/asamk/signal/commands/SendTypingCommand.java b/src/main/java/org/asamk/signal/commands/SendTypingCommand.java index f55981e3..4a2a038c 100644 --- a/src/main/java/org/asamk/signal/commands/SendTypingCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendTypingCommand.java @@ -12,15 +12,13 @@ import org.asamk.signal.manager.api.TypingAction; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.GroupSendingNotAllowedException; import org.asamk.signal.manager.groups.NotAGroupMemberException; -import org.asamk.signal.output.JsonWriter; import org.asamk.signal.output.OutputWriter; -import org.asamk.signal.output.PlainTextWriter; import org.asamk.signal.util.CommandUtil; -import org.asamk.signal.util.ErrorUtils; import java.io.IOException; import java.util.HashSet; -import java.util.Map; + +import static org.asamk.signal.util.SendMessageResultUtils.outputResult; public class SendTypingCommand implements JsonRpcLocalCommand { @@ -61,8 +59,7 @@ public class SendTypingCommand implements JsonRpcLocalCommand { try { final var results = m.sendTypingMessage(action, recipientIdentifiers); - outputResult(outputWriter, results.timestamp()); - ErrorUtils.handleSendMessageResults(results.results()); + outputResult(outputWriter, results); } catch (IOException e) { throw new UserErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass() .getSimpleName() + ")"); @@ -70,13 +67,4 @@ public class SendTypingCommand implements JsonRpcLocalCommand { throw new UserErrorException("Failed to send to group: " + e.getMessage()); } } - - private void outputResult(final OutputWriter outputWriter, final long timestamp) { - if (outputWriter instanceof PlainTextWriter writer) { - writer.println("{}", timestamp); - } else { - final var writer = (JsonWriter) outputWriter; - writer.write(Map.of("timestamp", timestamp)); - } - } } diff --git a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java index ed389719..f4f2db0b 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java @@ -9,6 +9,7 @@ import org.asamk.signal.commands.exceptions.UnexpectedErrorException; import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.AttachmentInvalidException; import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.api.SendGroupMessageResults; import org.asamk.signal.manager.api.UpdateGroup; import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupLinkState; @@ -20,13 +21,15 @@ import org.asamk.signal.output.JsonWriter; import org.asamk.signal.output.OutputWriter; import org.asamk.signal.output.PlainTextWriter; import org.asamk.signal.util.CommandUtil; -import org.asamk.signal.util.ErrorUtils; +import org.asamk.signal.util.SendMessageResultUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.util.HashMap; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class UpdateGroupCommand implements JsonRpcLocalCommand { @@ -121,14 +124,13 @@ public class UpdateGroupCommand implements JsonRpcLocalCommand { try { boolean isNewGroup = false; - Long timestamp = null; + SendGroupMessageResults groupMessageResults = null; if (groupId == null) { isNewGroup = true; var results = m.createGroup(groupName, groupMembers, groupAvatar == null ? null : new File(groupAvatar)); - timestamp = results.second().timestamp(); - ErrorUtils.handleSendMessageResults(results.second().results()); + groupMessageResults = results.second(); groupId = results.first(); groupName = null; groupMembers = null; @@ -154,10 +156,15 @@ public class UpdateGroupCommand implements JsonRpcLocalCommand { : groupSendMessagesPermission == GroupPermission.ONLY_ADMINS) .build()); if (results != null) { - timestamp = results.timestamp(); - ErrorUtils.handleSendMessageResults(results.results()); + if (groupMessageResults == null) { + groupMessageResults = results; + } else { + groupMessageResults = new SendGroupMessageResults(results.timestamp(), + Stream.concat(groupMessageResults.results().stream(), results.results().stream()) + .collect(Collectors.toList())); + } } - outputResult(outputWriter, timestamp, isNewGroup ? groupId : null); + outputResult(outputWriter, groupMessageResults, isNewGroup ? groupId : null); } catch (AttachmentInvalidException e) { throw new UserErrorException("Failed to add avatar attachment for group\": " + e.getMessage()); } catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) { @@ -168,24 +175,30 @@ public class UpdateGroupCommand implements JsonRpcLocalCommand { } } - private void outputResult(final OutputWriter outputWriter, final Long timestamp, final GroupId groupId) { + private void outputResult( + final OutputWriter outputWriter, final SendGroupMessageResults results, final GroupId groupId + ) { if (outputWriter instanceof PlainTextWriter writer) { if (groupId != null) { writer.println("Created new group: \"{}\"", groupId.toBase64()); } - if (timestamp != null) { - writer.println("{}", timestamp); + if (results != null) { + var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results.results()); + SendMessageResultUtils.printSendMessageResultErrors(writer, errors); + writer.println("{}", results.timestamp()); } } else { final var writer = (JsonWriter) outputWriter; - final var result = new HashMap<>(); - if (timestamp != null) { - result.put("timestamp", timestamp); + final var response = new HashMap<>(); + if (results != null) { + response.put("timestamp", results.timestamp()); + var jsonResults = SendMessageResultUtils.getJsonSendMessageResults(results.results()); + response.put("results", jsonResults); } if (groupId != null) { - result.put("groupId", groupId.toBase64()); + response.put("groupId", groupId.toBase64()); } - writer.write(result); + writer.write(response); } } } diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index e59c7f86..0c59429c 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -26,7 +26,7 @@ import org.asamk.signal.manager.groups.LastGroupAdminException; import org.asamk.signal.manager.groups.NotAGroupMemberException; import org.asamk.signal.manager.storage.recipients.Profile; import org.asamk.signal.manager.storage.recipients.RecipientAddress; -import org.asamk.signal.util.ErrorUtils; +import org.asamk.signal.util.SendMessageResultUtils; import org.freedesktop.dbus.DBusPath; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.exceptions.DBusException; @@ -781,7 +781,7 @@ public class DbusSignalImpl implements Signal { } private static void checkSendMessageResult(long timestamp, SendMessageResult result) throws DBusExecutionException { - var error = ErrorUtils.getErrorMessageFromSendMessageResult(result); + var error = SendMessageResultUtils.getErrorMessageFromSendMessageResult(result); if (error == null) { return; @@ -805,7 +805,7 @@ public class DbusSignalImpl implements Signal { return; } - var errors = ErrorUtils.getErrorMessagesFromSendMessageResults(results); + var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results); if (errors.size() == 0) { return; } @@ -828,7 +828,7 @@ public class DbusSignalImpl implements Signal { return; } - var errors = ErrorUtils.getErrorMessagesFromSendMessageResults(results); + var errors = SendMessageResultUtils.getErrorMessagesFromSendMessageResults(results); if (errors.size() == 0) { return; } diff --git a/src/main/java/org/asamk/signal/json/JsonRecipientAddress.java b/src/main/java/org/asamk/signal/json/JsonRecipientAddress.java new file mode 100644 index 00000000..1bd09e83 --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonRecipientAddress.java @@ -0,0 +1,12 @@ +package org.asamk.signal.json; + +import org.asamk.signal.manager.storage.recipients.RecipientAddress; + +import java.util.UUID; + +public record JsonRecipientAddress(String uuid, String number) { + + public static JsonRecipientAddress from(RecipientAddress address) { + return new JsonRecipientAddress(address.uuid().map(UUID::toString).orElse(null), address.number().orElse(null)); + } +} diff --git a/src/main/java/org/asamk/signal/json/JsonSendMessageResult.java b/src/main/java/org/asamk/signal/json/JsonSendMessageResult.java new file mode 100644 index 00000000..9b80a3aa --- /dev/null +++ b/src/main/java/org/asamk/signal/json/JsonSendMessageResult.java @@ -0,0 +1,38 @@ +package org.asamk.signal.json; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import org.asamk.signal.manager.api.SendMessageResult; +import org.asamk.signal.manager.groups.GroupId; + +public record JsonSendMessageResult( + JsonRecipientAddress recipientAddress, + @JsonInclude(JsonInclude.Include.NON_NULL) String groupId, + Type type, + @JsonInclude(JsonInclude.Include.NON_NULL) String token, + @JsonInclude(JsonInclude.Include.NON_NULL) Long retryAfterSeconds +) { + + public static JsonSendMessageResult from(SendMessageResult result) { + return from(result, null); + } + + public static JsonSendMessageResult from(SendMessageResult result, GroupId groupId) { + return new JsonSendMessageResult(JsonRecipientAddress.from(result.address()), + groupId != null ? groupId.toBase64() : null, + result.isSuccess() + ? Type.SUCCESS + : result.isNetworkFailure() + ? Type.NETWORK_FAILURE + : result.isUnregisteredFailure() ? Type.UNREGISTERED_FAILURE : Type.IDENTITY_FAILURE, + result.proofRequiredFailure() != null ? result.proofRequiredFailure().getToken() : null, + result.proofRequiredFailure() != null ? result.proofRequiredFailure().getRetryAfterSeconds() : null); + } + + public enum Type { + SUCCESS, + NETWORK_FAILURE, + UNREGISTERED_FAILURE, + IDENTITY_FAILURE, + } +} diff --git a/src/main/java/org/asamk/signal/util/ErrorUtils.java b/src/main/java/org/asamk/signal/util/SendMessageResultUtils.java similarity index 53% rename from src/main/java/org/asamk/signal/util/ErrorUtils.java rename to src/main/java/org/asamk/signal/util/SendMessageResultUtils.java index 3ca73163..0e13a200 100644 --- a/src/main/java/org/asamk/signal/util/ErrorUtils.java +++ b/src/main/java/org/asamk/signal/util/SendMessageResultUtils.java @@ -1,10 +1,14 @@ package org.asamk.signal.util; -import org.asamk.signal.commands.exceptions.CommandException; -import org.asamk.signal.commands.exceptions.IOErrorException; +import org.asamk.signal.json.JsonSendMessageResult; import org.asamk.signal.manager.api.ProofRequiredException; import org.asamk.signal.manager.api.RecipientIdentifier; +import org.asamk.signal.manager.api.SendGroupMessageResults; import org.asamk.signal.manager.api.SendMessageResult; +import org.asamk.signal.manager.api.SendMessageResults; +import org.asamk.signal.output.JsonWriter; +import org.asamk.signal.output.OutputWriter; +import org.asamk.signal.output.PlainTextWriter; import java.util.Collection; import java.util.List; @@ -12,23 +16,33 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; -public class ErrorUtils { +public class SendMessageResultUtils { - private ErrorUtils() { + private SendMessageResultUtils() { } - public static void handleSendMessageResults( - Map> mapResults - ) throws CommandException { - var errors = getErrorMessagesFromSendMessageResults(mapResults); - handleSendMessageResultErrors(errors); + public static void outputResult(final OutputWriter outputWriter, final SendGroupMessageResults sendMessageResults) { + if (outputWriter instanceof PlainTextWriter writer) { + var errors = getErrorMessagesFromSendMessageResults(sendMessageResults.results()); + printSendMessageResultErrors(writer, errors); + writer.println("{}", sendMessageResults.timestamp()); + } else { + final var writer = (JsonWriter) outputWriter; + var results = getJsonSendMessageResults(sendMessageResults.results()); + writer.write(Map.of("timestamp", sendMessageResults.timestamp(), "results", results)); + } } - public static void handleSendMessageResults( - Collection results - ) throws CommandException { - var errors = getErrorMessagesFromSendMessageResults(results); - handleSendMessageResultErrors(errors); + public static void outputResult(final OutputWriter outputWriter, final SendMessageResults sendMessageResults) { + if (outputWriter instanceof PlainTextWriter writer) { + var errors = getErrorMessagesFromSendMessageResults(sendMessageResults.results()); + printSendMessageResultErrors(writer, errors); + writer.println("{}", sendMessageResults.timestamp()); + } else { + final var writer = (JsonWriter) outputWriter; + var results = getJsonSendMessageResults(sendMessageResults.results()); + writer.write(Map.of("timestamp", sendMessageResults.timestamp(), "results", results)); + } } public static List getErrorMessagesFromSendMessageResults(final Map> mapResults) { @@ -36,7 +50,7 @@ public class ErrorUtils { .stream() .flatMap(entry -> entry.getValue() .stream() - .map(ErrorUtils::getErrorMessageFromSendMessageResult) + .map(SendMessageResultUtils::getErrorMessageFromSendMessageResult) .filter(Objects::nonNull) .map(error -> entry.getKey().getIdentifier() + ": " + error)) .collect(Collectors.toList()); @@ -44,7 +58,7 @@ public class ErrorUtils { public static List getErrorMessagesFromSendMessageResults(Collection results) { return results.stream() - .map(ErrorUtils::getErrorMessageFromSendMessageResult) + .map(SendMessageResultUtils::getErrorMessageFromSendMessageResult) .filter(Objects::nonNull) .collect(Collectors.toList()); } @@ -82,15 +96,24 @@ public class ErrorUtils { return null; } - private static void handleSendMessageResultErrors(List errors) throws CommandException { + public static void printSendMessageResultErrors(PlainTextWriter writer, List errors) { if (errors.size() == 0) { return; } - var message = new StringBuilder(); - message.append("Failed to send (some) messages:\n"); + writer.println("Failed to send (some) messages:"); for (var error : errors) { - message.append(error).append("\n"); + writer.println(error); } - throw new IOErrorException(message.toString(), null); + } + + public 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)); + }).collect(Collectors.toList()); + } + + public static List getJsonSendMessageResults(Collection results) { + return results.stream().map(JsonSendMessageResult::from).collect(Collectors.toList()); } } -- 2.50.1