Handle rate limit exception correctly when querying usernames

Fixes #1797
This commit is contained in:
AsamK 2025-07-12 11:03:28 +02:00
parent a96626c468
commit ca33249170
5 changed files with 34 additions and 14 deletions

View file

@ -58,7 +58,7 @@
},
{
"name":"java.lang.Throwable",
"methods":[{"name":"getMessage","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }]
"methods":[{"name":"getMessage","parameterTypes":[] }, {"name":"setStackTrace","parameterTypes":["java.lang.StackTraceElement[]"] }, {"name":"toString","parameterTypes":[] }]
},
{
"name":"java.lang.UnsatisfiedLinkError",
@ -126,6 +126,10 @@
"name":"org.signal.libsignal.net.NetworkException",
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
},
{
"name":"org.signal.libsignal.net.RetryLaterException",
"methods":[{"name":"<init>","parameterTypes":["long"] }]
},
{
"name":"org.signal.libsignal.protocol.DuplicateMessageException",
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]

View file

@ -96,7 +96,7 @@ public interface Manager extends Closeable {
*/
Map<String, UserStatus> getUserStatus(Set<String> numbers) throws IOException, RateLimitException;
Map<String, UsernameStatus> getUsernameStatus(Set<String> usernames);
Map<String, UsernameStatus> getUsernameStatus(Set<String> usernames) throws IOException;
void updateAccountAttributes(
String deviceName,

View file

@ -17,6 +17,7 @@ import org.whispersystems.signalservice.api.push.ServiceId.PNI;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.CdsiInvalidArgumentException;
import org.whispersystems.signalservice.api.push.exceptions.CdsiInvalidTokenException;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import java.io.IOException;
import java.util.Collection;
@ -68,7 +69,7 @@ public class RecipientHelper {
.toSignalServiceAddress();
}
public Set<RecipientId> resolveRecipients(Collection<RecipientIdentifier.Single> recipients) throws UnregisteredRecipientException {
public Set<RecipientId> resolveRecipients(Collection<RecipientIdentifier.Single> recipients) throws UnregisteredRecipientException, IOException {
final var recipientIds = new HashSet<RecipientId>(recipients.size());
for (var number : recipients) {
final var recipientId = resolveRecipient(number);
@ -91,7 +92,11 @@ public class RecipientHelper {
}
});
} else if (recipient instanceof RecipientIdentifier.Username(String username)) {
return resolveRecipientByUsernameOrLink(username, false);
try {
return resolveRecipientByUsernameOrLink(username, false);
} catch (Exception e) {
return null;
}
}
throw new AssertionError("Unexpected RecipientIdentifier: " + recipient);
}
@ -99,7 +104,7 @@ public class RecipientHelper {
public RecipientId resolveRecipientByUsernameOrLink(
String username,
boolean forceRefresh
) throws UnregisteredRecipientException {
) throws UnregisteredRecipientException, IOException {
final Username finalUsername;
try {
finalUsername = getUsernameFromUsernameOrLink(username);
@ -110,11 +115,15 @@ public class RecipientHelper {
try {
final var aci = handleResponseException(dependencies.getUsernameApi().getAciByUsername(finalUsername));
return account.getRecipientStore().resolveRecipientTrusted(aci, finalUsername.getUsername());
} catch (IOException e) {
throw new UnregisteredRecipientException(new org.asamk.signal.manager.api.RecipientAddress(null,
null,
null,
username));
} catch (NonSuccessfulResponseCodeException e) {
if (e.code == 404) {
throw new UnregisteredRecipientException(new org.asamk.signal.manager.api.RecipientAddress(null,
null,
null,
username));
}
logger.debug("Failed to get uuid for username: {}", username, e);
throw e;
}
}
return account.getRecipientStore().resolveRecipientByUsername(finalUsername.getUsername(), () -> {

View file

@ -285,7 +285,7 @@ public class ManagerImpl implements Manager {
}
@Override
public Map<String, UsernameStatus> getUsernameStatus(Set<String> usernames) {
public Map<String, UsernameStatus> getUsernameStatus(Set<String> usernames) throws IOException {
final var registeredUsers = new HashMap<String, RecipientAddress>();
for (final var username : usernames) {
try {

View file

@ -64,9 +64,16 @@ public class GetUserStatusCommand implements JsonRpcLocalCommand {
}
final var usernames = ns.<String>getList("username");
final var registeredUsernames = usernames == null
? Map.<String, UsernameStatus>of()
: m.getUsernameStatus(new HashSet<>(usernames));
final Map<String, UsernameStatus> registeredUsernames;
try {
registeredUsernames = usernames == null ? Map.of() : m.getUsernameStatus(new HashSet<>(usernames));
} catch (IOException e) {
throw new IOErrorException("Unable to check if users are registered: "
+ e.getMessage()
+ " ("
+ e.getClass().getSimpleName()
+ ")", e);
}
// Output
switch (outputWriter) {