]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/util/SendMessageResultUtils.java
Reformat files
[signal-cli] / src / main / java / org / asamk / signal / util / SendMessageResultUtils.java
1 package org.asamk.signal.util;
2
3 import org.asamk.signal.commands.exceptions.CommandException;
4 import org.asamk.signal.commands.exceptions.RateLimitErrorException;
5 import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
6 import org.asamk.signal.commands.exceptions.UserErrorException;
7 import org.asamk.signal.json.JsonSendMessageResult;
8 import org.asamk.signal.manager.api.ProofRequiredException;
9 import org.asamk.signal.manager.api.RateLimitException;
10 import org.asamk.signal.manager.api.RecipientIdentifier;
11 import org.asamk.signal.manager.api.SendGroupMessageResults;
12 import org.asamk.signal.manager.api.SendMessageResult;
13 import org.asamk.signal.manager.api.SendMessageResults;
14 import org.asamk.signal.output.JsonWriter;
15 import org.asamk.signal.output.OutputWriter;
16 import org.asamk.signal.output.PlainTextWriter;
17
18 import java.util.Collection;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Objects;
22 import java.util.stream.Collectors;
23
24 public class SendMessageResultUtils {
25
26 private SendMessageResultUtils() {
27 }
28
29 public static void outputResult(final OutputWriter outputWriter, final SendGroupMessageResults sendMessageResults) {
30 switch (outputWriter) {
31 case PlainTextWriter writer -> {
32 var errors = getErrorMessagesFromSendMessageResults(sendMessageResults.results());
33 printSendMessageResultErrors(writer, errors);
34 writer.println("{}", sendMessageResults.timestamp());
35 }
36 case JsonWriter writer -> {
37 var results = getJsonSendMessageResults(sendMessageResults.results());
38 writer.write(Map.of("timestamp", sendMessageResults.timestamp(), "results", results));
39 }
40 }
41 }
42
43 public static void outputResult(
44 final OutputWriter outputWriter,
45 final SendMessageResults sendMessageResults
46 ) throws CommandException {
47 switch (outputWriter) {
48 case PlainTextWriter writer -> {
49 var errors = getErrorMessagesFromSendMessageResults(sendMessageResults.results());
50 printSendMessageResultErrors(writer, errors);
51 writer.println("{}", sendMessageResults.timestamp());
52 }
53 case JsonWriter writer -> {
54 var results = getJsonSendMessageResults(sendMessageResults.results());
55 writer.write(Map.of("timestamp", sendMessageResults.timestamp(), "results", results));
56 }
57 }
58 if (!sendMessageResults.hasSuccess()) {
59 if (sendMessageResults.hasOnlyUntrustedIdentity()) {
60 throw new UntrustedKeyErrorException("Failed to send message due to untrusted identities");
61 } else if (sendMessageResults.hasOnlyRateLimitFailure()) {
62 throw new RateLimitErrorException("Failed to send message due to rate limiting",
63 new RateLimitException(0));
64 } else {
65 throw new UserErrorException("Failed to send message");
66 }
67 }
68 }
69
70 public static List<String> getErrorMessagesFromSendMessageResults(final Map<RecipientIdentifier, List<SendMessageResult>> mapResults) {
71 return mapResults.entrySet()
72 .stream()
73 .flatMap(entry -> entry.getValue()
74 .stream()
75 .map(SendMessageResultUtils::getErrorMessageFromSendMessageResult)
76 .filter(Objects::nonNull)
77 .map(error -> entry.getKey().getIdentifier() + ": " + error))
78 .toList();
79 }
80
81 public static List<String> getErrorMessagesFromSendMessageResults(Collection<SendMessageResult> results) {
82 return results.stream()
83 .map(SendMessageResultUtils::getErrorMessageFromSendMessageResult)
84 .filter(Objects::nonNull)
85 .toList();
86 }
87
88 public static String getErrorMessageFromSendMessageResult(SendMessageResult result) {
89 var identifier = result.address().getLegacyIdentifier();
90 if (result.proofRequiredFailure() != null) {
91 final var failure = result.proofRequiredFailure();
92 return String.format(
93 "CAPTCHA proof required for sending to \"%s\", available options \"%s\" with challenge token \"%s\", or wait \"%d\" seconds.\n"
94 + (
95 failure.getOptions().contains(ProofRequiredException.Option.CAPTCHA)
96 ? """
97 To get the captcha token, go to https://signalcaptchas.org/challenge/generate.html
98 After solving the captcha, right-click on the "Open Signal" link and copy the link.
99 Use the following command to submit the captcha token:
100 signal-cli submitRateLimitChallenge --challenge CHALLENGE_TOKEN --captcha CAPTCHA_TOKEN"""
101 : ""
102 ),
103 identifier,
104 failure.getOptions()
105 .stream()
106 .map(ProofRequiredException.Option::toString)
107 .collect(Collectors.joining(", ")),
108 failure.getToken(),
109 failure.getRetryAfterSeconds());
110 } else if (result.isNetworkFailure()) {
111 return String.format("Network failure for \"%s\"", identifier);
112 } else if (result.isRateLimitFailure()) {
113 return String.format("Rate limit failure for \"%s\"", identifier);
114 } else if (result.isUnregisteredFailure()) {
115 return String.format("Unregistered user \"%s\"", identifier);
116 } else if (result.isIdentityFailure()) {
117 return String.format("Untrusted Identity for \"%s\"", identifier);
118 }
119 return null;
120 }
121
122 public static void printSendMessageResultErrors(PlainTextWriter writer, List<String> errors) {
123 if (errors.isEmpty()) {
124 return;
125 }
126 writer.println("Failed to send (some) messages:");
127 for (var error : errors) {
128 writer.println(error);
129 }
130 }
131
132 private static List<JsonSendMessageResult> getJsonSendMessageResults(final Map<RecipientIdentifier, List<SendMessageResult>> mapResults) {
133 return mapResults.entrySet().stream().flatMap(entry -> {
134 final var groupId = entry.getKey() instanceof RecipientIdentifier.Group g ? g.groupId() : null;
135 return entry.getValue().stream().map(r -> JsonSendMessageResult.from(r, groupId));
136 }).toList();
137 }
138
139 public static List<JsonSendMessageResult> getJsonSendMessageResults(Collection<SendMessageResult> results) {
140 return results.stream().map(JsonSendMessageResult::from).toList();
141 }
142 }