1 package org
.asamk
.signal
.util
;
3 import org
.asamk
.signal
.commands
.exceptions
.CommandException
;
4 import org
.asamk
.signal
.commands
.exceptions
.IOErrorException
;
5 import org
.asamk
.signal
.manager
.api
.ProofRequiredException
;
6 import org
.asamk
.signal
.manager
.api
.RecipientIdentifier
;
7 import org
.asamk
.signal
.manager
.api
.SendMessageResult
;
9 import java
.util
.Collection
;
10 import java
.util
.List
;
12 import java
.util
.Objects
;
13 import java
.util
.stream
.Collectors
;
15 public class ErrorUtils
{
17 private ErrorUtils() {
20 public static void handleSendMessageResults(
21 Map
<RecipientIdentifier
, List
<SendMessageResult
>> mapResults
22 ) throws CommandException
{
23 var errors
= getErrorMessagesFromSendMessageResults(mapResults
);
24 handleSendMessageResultErrors(errors
);
27 public static void handleSendMessageResults(
28 Collection
<SendMessageResult
> results
29 ) throws CommandException
{
30 var errors
= getErrorMessagesFromSendMessageResults(results
);
31 handleSendMessageResultErrors(errors
);
34 public static List
<String
> getErrorMessagesFromSendMessageResults(final Map
<RecipientIdentifier
, List
<SendMessageResult
>> mapResults
) {
35 return mapResults
.entrySet()
37 .flatMap(entry
-> entry
.getValue()
39 .map(ErrorUtils
::getErrorMessageFromSendMessageResult
)
40 .filter(Objects
::nonNull
)
41 .map(error
-> entry
.getKey().getIdentifier() + ": " + error
))
42 .collect(Collectors
.toList());
45 public static List
<String
> getErrorMessagesFromSendMessageResults(Collection
<SendMessageResult
> results
) {
46 return results
.stream()
47 .map(ErrorUtils
::getErrorMessageFromSendMessageResult
)
48 .filter(Objects
::nonNull
)
49 .collect(Collectors
.toList());
52 public static String
getErrorMessageFromSendMessageResult(SendMessageResult result
) {
53 var identifier
= result
.address().getLegacyIdentifier();
54 if (result
.proofRequiredFailure() != null) {
55 final var failure
= result
.proofRequiredFailure();
57 "CAPTCHA proof required for sending to \"%s\", available options \"%s\" with challenge token \"%s\", or wait \"%d\" seconds.\n"
59 failure
.getOptions().contains(ProofRequiredException
.Option
.RECAPTCHA
)
61 To get the captcha token, go to https://signalcaptchas.org/challenge/generate.html
62 Check the developer tools (F12) console for a failed redirect to signalcaptcha://
63 Everything after signalcaptcha:// is the captcha token.
64 Use the following command to submit the captcha token:
65 signal-cli submitRateLimitChallenge --challenge CHALLENGE_TOKEN --captcha CAPTCHA_TOKEN"""
71 .map(ProofRequiredException
.Option
::toString
)
72 .collect(Collectors
.joining(", ")),
74 failure
.getRetryAfterSeconds());
75 } else if (result
.isNetworkFailure()) {
76 return String
.format("Network failure for \"%s\"", identifier
);
77 } else if (result
.isUnregisteredFailure()) {
78 return String
.format("Unregistered user \"%s\"", identifier
);
79 } else if (result
.isIdentityFailure()) {
80 return String
.format("Untrusted Identity for \"%s\"", identifier
);
85 private static void handleSendMessageResultErrors(List
<String
> errors
) throws CommandException
{
86 if (errors
.size() == 0) {
89 var message
= new StringBuilder();
90 message
.append("Failed to send (some) messages:\n");
91 for (var error
: errors
) {
92 message
.append(error
).append("\n");
94 throw new IOErrorException(message
.toString(), null);