Add signal.me username support.

This commit is contained in:
Cody Henthorne 2022-09-08 10:04:30 -04:00 committed by Greyson Parrelli
parent 9b9453734c
commit 0685cf4e51
2 changed files with 61 additions and 20 deletions

View file

@ -41,8 +41,10 @@ import org.thoughtcrime.securesms.proxy.ProxyBottomSheetFragment;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog; import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import org.whispersystems.signalservice.api.push.ServiceId;
import java.io.IOException; import java.io.IOException;
import java.util.Optional;
public class CommunicationActions { public class CommunicationActions {
@ -266,36 +268,49 @@ public class CommunicationActions {
} }
/** /**
* If the url is a proxy link it will handle it. * If the url is a signal.me link it will handle it.
* Otherwise returns false, indicating was not a proxy link.
*/ */
public static boolean handlePotentialSignalMeUrl(@NonNull FragmentActivity activity, @NonNull String potentialUrl) { public static void handlePotentialSignalMeUrl(@NonNull FragmentActivity activity, @NonNull String potentialUrl) {
String e164 = SignalMeUtil.parseE164FromLink(activity, potentialUrl); String e164 = SignalMeUtil.parseE164FromLink(activity, potentialUrl);
String username = SignalMeUtil.parseUsernameFromLink(potentialUrl);
if (e164 != null) { if (e164 != null || username != null) {
SimpleProgressDialog.DismissibleDialog dialog = SimpleProgressDialog.showDelayed(activity, 500, 500); SimpleProgressDialog.DismissibleDialog dialog = SimpleProgressDialog.showDelayed(activity, 500, 500);
SimpleTask.run(() -> { SimpleTask.run(() -> {
Recipient recipient = Recipient.external(activity, e164); Recipient recipient = Recipient.UNKNOWN;
if (e164 != null) {
recipient = Recipient.external(activity, e164);
if (!recipient.isRegistered() || !recipient.hasServiceId()) { if (!recipient.isRegistered() || !recipient.hasServiceId()) {
try { try {
ContactDiscovery.refresh(activity, recipient, false); ContactDiscovery.refresh(activity, recipient, false);
recipient = Recipient.resolved(recipient.getId()); recipient = Recipient.resolved(recipient.getId());
} catch (IOException e) { } catch (IOException e) {
Log.w(TAG, "[handlePotentialMeUrl] Failed to refresh directory for new contact."); Log.w(TAG, "[handlePotentialSignalMeUrl] Failed to refresh directory for new contact.");
}
}
} else {
Optional<ServiceId> serviceId = UsernameUtil.fetchAciForUsername(username);
if (serviceId.isPresent()) {
recipient = Recipient.externalUsername(serviceId.get(), username);
} }
} }
return recipient; return recipient;
}, recipient -> { }, recipient -> {
dialog.dismiss(); dialog.dismiss();
startConversation(activity, recipient, null);
});
return true; if (recipient != Recipient.UNKNOWN) {
} else { startConversation(activity, recipient, null);
return false; } else if (username != null) {
new MaterialAlertDialogBuilder(activity)
.setTitle(R.string.ContactSelectionListFragment_username_not_found)
.setMessage(activity.getString(R.string.ContactSelectionListFragment_s_is_not_a_signal_user, username))
.setPositiveButton(android.R.string.ok, null)
.show();
}
});
} }
} }

View file

@ -9,13 +9,17 @@ import com.google.i18n.phonenumbers.PhoneNumberUtil;
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter; import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
class SignalMeUtil { class SignalMeUtil {
private static final String HOST = "signal.me"; private static final String HOST = "^(https|sgnl)://" + "signal\\.me";
private static final Pattern HOST_PATTERN = Pattern.compile("^(https|sgnl)://" + HOST + "/#p/(\\+[0-9]+)$"); private static final Pattern E164_PATTERN = Pattern.compile(HOST + "/#p/(\\+[0-9]+)$");
private static final Pattern USERNAME_PATTERN = Pattern.compile(HOST + "/#u/(.+)$");
/** /**
* If this is a valid signal.me link and has a valid e164, it will return the e164. Otherwise, it will return null. * If this is a valid signal.me link and has a valid e164, it will return the e164. Otherwise, it will return null.
@ -25,7 +29,7 @@ class SignalMeUtil {
return null; return null;
} }
Matcher matcher = HOST_PATTERN.matcher(link); Matcher matcher = E164_PATTERN.matcher(link);
if (matcher.matches()) { if (matcher.matches()) {
String e164 = matcher.group(2); String e164 = matcher.group(2);
@ -39,4 +43,26 @@ class SignalMeUtil {
return null; return null;
} }
} }
/**
* If this is a valid signal.me link and has a valid username, it will return the username. Otherwise, it will return null.
*/
public static @Nullable String parseUsernameFromLink(@Nullable String link) {
if (Util.isEmpty(link)) {
return null;
}
Matcher matcher = USERNAME_PATTERN.matcher(link);
if (matcher.matches()) {
String username = matcher.group(2);
try {
return username == null || username.isEmpty() ? null : URLDecoder.decode(username, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
return null;
}
} else {
return null;
}
}
} }